--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1,17 +1,17 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* 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/. */
/* eslint-env mozilla/browser-window */
-class TabBrowser {
- constructor() {
+window._gBrowser = {
+ init() {
this.requiresAddonInterpositions = true;
ChromeUtils.defineModuleGetter(this, "AsyncTabSwitcher",
"resource:///modules/AsyncTabSwitcher.jsm");
XPCOMUtils.defineLazyServiceGetters(this, {
_unifiedComplete: ["@mozilla.org/autocomplete/search;1?name=unifiedcomplete", "mozIPlacesAutoComplete"],
serializationHelper: ["@mozilla.org/network/serialization-helper;1", "nsISerializationHelper"],
@@ -249,231 +249,231 @@ class TabBrowser {
"browser.tabs.tabMinWidth", this._tabMinWidthLimit,
(pref, prevValue, newValue) => this.tabMinWidth = newValue,
newValue => Math.max(newValue, this._tabMinWidthLimit),
);
this.tabMinWidth = this.tabMinWidthPref;
this._setupEventListeners();
- }
+ },
get tabContextMenu() {
return this.tabContainer.contextMenu;
- }
+ },
get visibleTabs() {
if (!this._visibleTabs)
this._visibleTabs = Array.filter(this.tabs,
tab => !tab.hidden && !tab.closing);
return this._visibleTabs;
- }
+ },
get _numPinnedTabs() {
for (var i = 0; i < this.tabs.length; i++) {
if (!this.tabs[i].pinned)
break;
}
return i;
- }
+ },
get popupAnchor() {
if (this.mCurrentTab._popupAnchor) {
return this.mCurrentTab._popupAnchor;
}
let stack = this.mCurrentBrowser.parentNode;
// Create an anchor for the popup
let popupAnchor = document.createElementNS(this._XUL_NS, "hbox");
popupAnchor.className = "popup-anchor";
popupAnchor.hidden = true;
stack.appendChild(popupAnchor);
return this.mCurrentTab._popupAnchor = popupAnchor;
- }
+ },
set selectedTab(val) {
if (gNavToolbox.collapsed && !this._allowTabChange) {
return this.tabbox.selectedTab;
}
// Update the tab
this.tabbox.selectedTab = val;
return val;
- }
+ },
get selectedTab() {
return this.mCurrentTab;
- }
+ },
get selectedBrowser() {
return this.mCurrentBrowser;
- }
+ },
/**
* BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
* MAKE SURE TO ADD IT HERE AS WELL.
*/
get canGoBack() {
return this.mCurrentBrowser.canGoBack;
- }
+ },
get canGoForward() {
return this.mCurrentBrowser.canGoForward;
- }
+ },
goBack() {
return this.mCurrentBrowser.goBack();
- }
+ },
goForward() {
return this.mCurrentBrowser.goForward();
- }
+ },
reload() {
return this.mCurrentBrowser.reload();
- }
+ },
reloadWithFlags(aFlags) {
return this.mCurrentBrowser.reloadWithFlags(aFlags);
- }
+ },
stop() {
return this.mCurrentBrowser.stop();
- }
+ },
/**
* throws exception for unknown schemes
*/
loadURI(aURI, aReferrerURI, aCharset) {
return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset);
- }
+ },
/**
* throws exception for unknown schemes
*/
loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData) {
// Note - the callee understands both:
// (a) loadURIWithFlags(aURI, aFlags, ...)
// (b) loadURIWithFlags(aURI, { flags: aFlags, ... })
// Forwarding it as (a) here actually supports both (a) and (b),
// so you can call us either way too.
return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
- }
+ },
goHome() {
return this.mCurrentBrowser.goHome();
- }
+ },
gotoIndex(aIndex) {
return this.mCurrentBrowser.gotoIndex(aIndex);
- }
+ },
set homePage(val) {
this.mCurrentBrowser.homePage = val;
return val;
- }
+ },
get homePage() {
return this.mCurrentBrowser.homePage;
- }
+ },
get currentURI() {
return this.mCurrentBrowser.currentURI;
- }
+ },
get finder() {
return this.mCurrentBrowser.finder;
- }
+ },
get docShell() {
return this.mCurrentBrowser.docShell;
- }
+ },
get webNavigation() {
return this.mCurrentBrowser.webNavigation;
- }
+ },
get webBrowserFind() {
return this.mCurrentBrowser.webBrowserFind;
- }
+ },
get webProgress() {
return this.mCurrentBrowser.webProgress;
- }
+ },
get contentWindow() {
return this.mCurrentBrowser.contentWindow;
- }
+ },
get contentWindowAsCPOW() {
return this.mCurrentBrowser.contentWindowAsCPOW;
- }
+ },
get sessionHistory() {
return this.mCurrentBrowser.sessionHistory;
- }
+ },
get markupDocumentViewer() {
return this.mCurrentBrowser.markupDocumentViewer;
- }
+ },
get contentDocument() {
return this.mCurrentBrowser.contentDocument;
- }
+ },
get contentDocumentAsCPOW() {
return this.mCurrentBrowser.contentDocumentAsCPOW;
- }
+ },
get contentTitle() {
return this.mCurrentBrowser.contentTitle;
- }
+ },
get contentPrincipal() {
return this.mCurrentBrowser.contentPrincipal;
- }
+ },
get securityUI() {
return this.mCurrentBrowser.securityUI;
- }
+ },
set fullZoom(val) {
this.mCurrentBrowser.fullZoom = val;
- }
+ },
get fullZoom() {
return this.mCurrentBrowser.fullZoom;
- }
+ },
set textZoom(val) {
this.mCurrentBrowser.textZoom = val;
- }
+ },
get textZoom() {
return this.mCurrentBrowser.textZoom;
- }
+ },
get isSyntheticDocument() {
return this.mCurrentBrowser.isSyntheticDocument;
- }
+ },
set userTypedValue(val) {
return this.mCurrentBrowser.userTypedValue = val;
- }
+ },
get userTypedValue() {
return this.mCurrentBrowser.userTypedValue;
- }
+ },
set tabMinWidth(val) {
this.tabContainer.style.setProperty("--tab-min-width", val + "px");
return val;
- }
+ },
isFindBarInitialized(aTab) {
return (aTab || this.selectedTab)._findBar != undefined;
- }
+ },
getFindBar(aTab) {
if (!aTab)
aTab = this.selectedTab;
if (aTab._findBar)
return aTab._findBar;
@@ -490,35 +490,35 @@ class TabBrowser {
aTab._findBar = findBar;
let event = document.createEvent("Events");
event.initEvent("TabFindInitialized", true, false);
aTab.dispatchEvent(event);
return findBar;
- }
+ },
getStatusPanel() {
if (!this._statusPanel) {
this._statusPanel = document.createElementNS(this._XUL_NS, "statuspanel");
this._statusPanel.setAttribute("inactive", "true");
this._statusPanel.setAttribute("layer", "true");
this._appendStatusPanel();
}
return this._statusPanel;
- }
+ },
_appendStatusPanel() {
if (this._statusPanel) {
let browser = this.selectedBrowser;
let browserContainer = this.getBrowserContainer(browser);
browserContainer.insertBefore(this._statusPanel, browser.parentNode.nextSibling);
}
- }
+ },
pinTab(aTab) {
if (aTab.pinned)
return;
if (aTab.hidden)
this.showTab(aTab);
@@ -528,17 +528,17 @@ class TabBrowser {
this.tabContainer._positionPinnedTabs();
this.tabContainer._updateCloseButtons();
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: true });
let event = document.createEvent("Events");
event.initEvent("TabPinned", true, false);
aTab.dispatchEvent(event);
- }
+ },
unpinTab(aTab) {
if (!aTab.pinned)
return;
this.moveTabTo(aTab, this._numPinnedTabs - 1);
aTab.removeAttribute("pinned");
aTab.style.marginInlineStart = "";
@@ -546,30 +546,30 @@ class TabBrowser {
this.tabContainer._positionPinnedTabs();
this.tabContainer._updateCloseButtons();
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: false });
let event = document.createEvent("Events");
event.initEvent("TabUnpinned", true, false);
aTab.dispatchEvent(event);
- }
+ },
previewTab(aTab, aCallback) {
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;
}
- }
+ },
syncThrobberAnimations(aTab) {
aTab.ownerGlobal.promiseDocumentFlushed(() => {
if (!aTab.parentNode) {
return;
}
const animations =
@@ -602,40 +602,40 @@ class TabBrowser {
// the playState, since reading the playState of
// a CSSAnimation object will flush style.
if (animation.currentTime !== null) {
animation.startTime = firstStartTime;
}
}
});
});
- }
+ },
getBrowserAtIndex(aIndex) {
return this.browsers[aIndex];
- }
+ },
getBrowserIndexForDocument(aDocument) {
var tab = this._getTabForContentWindow(aDocument.defaultView);
return tab ? tab._tPos : -1;
- }
+ },
getBrowserForDocument(aDocument) {
var tab = this._getTabForContentWindow(aDocument.defaultView);
return tab ? tab.linkedBrowser : null;
- }
+ },
getBrowserForContentWindow(aWindow) {
var tab = this._getTabForContentWindow(aWindow);
return tab ? tab.linkedBrowser : null;
- }
+ },
getBrowserForOuterWindowID(aID) {
return this._outerWindowIDBrowserMap.get(aID);
- }
+ },
_getTabForContentWindow(aWindow) {
// When not using remote browsers, we can take a fast path by getting
// directly from the content window to the browser without looping
// over all browsers.
if (!gMultiProcessBrowser) {
let browser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
@@ -646,52 +646,52 @@ class TabBrowser {
for (let i = 0; i < this.browsers.length; i++) {
// NB: We use contentWindowAsCPOW so that this code works both
// for remote browsers as well. aWindow may be a CPOW.
if (this.browsers[i].contentWindowAsCPOW == aWindow)
return this.tabs[i];
}
return null;
- }
+ },
getTabForBrowser(aBrowser) {
return this._tabForBrowser.get(aBrowser);
- }
+ },
getNotificationBox(aBrowser) {
return this.getSidebarContainer(aBrowser).parentNode;
- }
+ },
getSidebarContainer(aBrowser) {
return this.getBrowserContainer(aBrowser).parentNode;
- }
+ },
getBrowserContainer(aBrowser) {
return (aBrowser || this.mCurrentBrowser).parentNode.parentNode;
- }
+ },
getTabModalPromptBox(aBrowser) {
let browser = (aBrowser || this.mCurrentBrowser);
if (!browser.tabModalPromptBox) {
browser.tabModalPromptBox = new TabModalPromptBox(browser);
}
return browser.tabModalPromptBox;
- }
+ },
getTabFromAudioEvent(aEvent) {
if (!Services.prefs.getBoolPref("browser.tabs.showAudioPlayingIcon") ||
!aEvent.isTrusted) {
return null;
}
var browser = aEvent.originalTarget;
var tab = this.getTabForBrowser(browser);
return tab;
- }
+ },
_callProgressListeners(aBrowser, aMethod, aArguments, aCallGlobalListeners, aCallTabsListeners) {
var rv = true;
function callListeners(listeners, args) {
for (let p of listeners) {
if (aMethod in p) {
try {
@@ -717,17 +717,17 @@ class TabBrowser {
// eslint-disable-next-line mozilla/no-compare-against-boolean-literals
if (aCallTabsListeners != false) {
aArguments.unshift(aBrowser);
callListeners(this.mTabsProgressListeners, aArguments);
}
return rv;
- }
+ },
/**
* Determine if a URI is an about: page pointing to a local resource.
*/
_isLocalAboutURI(aURI, aResolvedURI) {
if (!aURI.schemeIs("about")) {
return false;
}
@@ -747,28 +747,28 @@ class TabBrowser {
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, // securityFlags
Ci.nsIContentPolicy.TYPE_OTHER // contentPolicyType
).URI;
return resolvedURI.schemeIs("jar") || resolvedURI.schemeIs("file");
} catch (ex) {
// aURI might be invalid.
return false;
}
- }
+ },
storeIcon(aBrowser, aURI, aLoadingPrincipal, aRequestContextID) {
try {
if (!(aURI instanceof Ci.nsIURI)) {
aURI = makeURI(aURI);
}
PlacesUIUtils.loadFavicon(aBrowser, aLoadingPrincipal, aURI, aRequestContextID);
} catch (ex) {
Cu.reportError(ex);
}
- }
+ },
setIcon(aTab, aURI, aLoadingPrincipal, aRequestContextID) {
let browser = this.getBrowserForTab(aTab);
browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
let loadingPrincipal = aLoadingPrincipal ||
Services.scriptSecurityManager.getSystemPrincipal();
let requestContextID = aRequestContextID || 0;
let sizedIconUrl = browser.mIconURL || "";
@@ -786,36 +786,36 @@ class TabBrowser {
aTab.removeAttribute("iconloadingprincipal");
delete browser.mIconLoadingPrincipal;
aTab.removeAttribute("image");
}
this._tabAttrModified(aTab, ["image"]);
}
this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]);
- }
+ },
getIcon(aTab) {
let browser = aTab ? this.getBrowserForTab(aTab) : this.selectedBrowser;
return browser.mIconURL;
- }
+ },
setPageInfo(aURL, aDescription, aPreviewImage) {
if (aURL) {
let pageInfo = { url: aURL, description: aDescription, previewImageURL: aPreviewImage };
PlacesUtils.history.update(pageInfo).catch(Cu.reportError);
}
- }
+ },
shouldLoadFavIcon(aURI) {
return (aURI &&
Services.prefs.getBoolPref("browser.chrome.site_icons") &&
Services.prefs.getBoolPref("browser.chrome.favicons") &&
("schemeIs" in aURI) && (aURI.schemeIs("http") || aURI.schemeIs("https")));
- }
+ },
useDefaultIcon(aTab) {
let browser = this.getBrowserForTab(aTab);
let documentURI = browser.documentURI;
let requestContextID = browser.contentRequestContextID;
let loadingPrincipal = browser.contentPrincipal;
let icon = null;
@@ -837,23 +837,23 @@ class TabBrowser {
let url = documentURI.prePath + "/favicon.ico";
if (!this.isFailedIcon(url)) {
icon = url;
this.storeIcon(browser, icon, loadingPrincipal, requestContextID);
}
}
this.setIcon(aTab, icon, loadingPrincipal, requestContextID);
- }
+ },
isFailedIcon(aURI) {
if (!(aURI instanceof Ci.nsIURI))
aURI = makeURI(aURI);
return PlacesUtils.favicons.isFailedFavicon(aURI);
- }
+ },
getWindowTitleForBrowser(aBrowser) {
var newTitle = "";
var docElement = document.documentElement;
var sep = docElement.getAttribute("titlemenuseparator");
let tab = this.getTabForBrowser(aBrowser);
let docTitle;
@@ -886,21 +886,21 @@ class TabBrowser {
if (uri.scheme == "about")
newTitle = uri.spec + sep + newTitle;
else
newTitle = uri.prePath + sep + newTitle;
}
} catch (e) {}
return newTitle;
- }
+ },
updateTitlebar() {
document.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
- }
+ },
updateCurrentBrowser(aForceUpdate) {
var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
return;
if (!aForceUpdate) {
document.commandDispatcher.lock();
@@ -1115,17 +1115,17 @@ class TabBrowser {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
if (!aForceUpdate)
TelemetryStopwatch.finish("FX_TAB_SWITCH_UPDATE_MS");
- }
+ },
_adjustFocusBeforeTabSwitch(oldTab, newTab) {
if (this._previewMode) {
return;
}
let oldBrowser = oldTab.linkedBrowser;
let newBrowser = newTab.linkedBrowser;
@@ -1151,17 +1151,17 @@ class TabBrowser {
gURLBar &&
gURLBar.focused;
if (!keepFocusOnUrlBar) {
// Clear focus so that _adjustFocusAfterTabSwitch can detect if
// some element has been focused and respect that.
document.activeElement.blur();
}
}
- }
+ },
_adjustFocusAfterTabSwitch(newTab) {
// Don't steal focus from the tab bar.
if (document.activeElement == newTab)
return;
let newBrowser = this.getBrowserForTab(newTab);
@@ -1218,31 +1218,31 @@ class TabBrowser {
// 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);
- }
+ },
_tabAttrModified(aTab, aChanged) {
if (aTab.closing)
return;
let event = new CustomEvent("TabAttrModified", {
bubbles: true,
cancelable: false,
detail: {
changed: aChanged,
}
});
aTab.dispatchEvent(event);
- }
+ },
setBrowserSharing(aBrowser, aState) {
let tab = this.getTabForBrowser(aBrowser);
if (!tab)
return;
if (aState.sharing) {
tab._sharingState = aState;
@@ -1254,37 +1254,37 @@ class TabBrowser {
} else {
tab._sharingState = null;
tab.removeAttribute("sharing");
}
this._tabAttrModified(tab, ["sharing"]);
if (aBrowser == this.mCurrentBrowser)
gIdentityHandler.updateSharingIndicator();
- }
+ },
getTabSharingState(aTab) {
// Normalize the state object for consumers (ie.extensions).
let state = Object.assign({}, aTab._sharingState);
return {
camera: !!state.camera,
microphone: !!state.microphone,
screen: state.screen && state.screen.replace("Paused", ""),
};
- }
+ },
setInitialTabTitle(aTab, aTitle, aOptions) {
if (aTitle) {
if (!aTab.getAttribute("label")) {
aTab._labelIsInitialTitle = true;
}
this._setTabLabel(aTab, aTitle, aOptions);
}
- }
+ },
setTabTitle(aTab) {
var browser = this.getBrowserForTab(aTab);
var title = browser.contentTitle;
// Don't replace an initially set label with the URL while the tab
// is loading.
if (aTab._labelIsInitialTitle) {
@@ -1332,17 +1332,17 @@ class TabBrowser {
} catch (ex) { /* Do nothing. */ }
} else {
// Still no title? Fall back to our untitled string.
title = gTabBrowserBundle.GetStringFromName("tabs.emptyTabTitle");
}
}
return this._setTabLabel(aTab, title, { isContentTitle });
- }
+ },
_setTabLabel(aTab, aLabel, aOptions) {
if (!aLabel) {
return false;
}
aTab._fullLabel = aLabel;
@@ -1374,17 +1374,17 @@ class TabBrowser {
this._tabAttrModified(aTab, ["label"]);
}
if (aTab.selected) {
this.updateTitlebar();
}
return true;
- }
+ },
loadOneTab(aURI, aReferrerURI, aCharset, aPostData, aLoadInBackground, aAllowThirdPartyFixup) {
var aTriggeringPrincipal;
var aReferrerPolicy;
var aFromExternal;
var aRelatedToCurrent;
var aAllowMixedContent;
var aSkipAnimation;
@@ -1457,17 +1457,17 @@ class TabBrowser {
nextTabParentId: aNextTabParentId,
focusUrlBar: aFocusUrlBar,
name: aName
});
if (!bgLoad)
this.selectedTab = tab;
return tab;
- }
+ },
loadTabs(aURIs, aLoadInBackground, aReplace) {
let aTriggeringPrincipal;
let aAllowThirdPartyFixup;
let aTargetTab;
let aNewIndex = -1;
let aPostDatas = [];
let aUserContextId;
@@ -1554,17 +1554,17 @@ class TabBrowser {
});
if (targetTabIndex !== -1)
this.moveTabTo(tab, ++tabNum);
}
if (firstTabAdded && !aLoadInBackground) {
this.selectedTab = firstTabAdded;
}
- }
+ },
updateBrowserRemoteness(aBrowser, aShouldBeRemote, aOptions) {
aOptions = aOptions || {};
let isRemote = aBrowser.getAttribute("remote") == "true";
if (!gMultiProcessBrowser && aShouldBeRemote) {
throw new Error("Cannot switch to remote browser in a window " +
"without the remote tabs load context.");
@@ -1710,17 +1710,17 @@ class TabBrowser {
this.getFindBar(tab).browser = aBrowser;
}
evt = document.createEvent("Events");
evt.initEvent("TabRemotenessChange", true, false);
tab.dispatchEvent(evt);
return true;
- }
+ },
updateBrowserRemotenessByURL(aBrowser, aURL, aOptions) {
aOptions = aOptions || {};
if (!gMultiProcessBrowser)
return this.updateBrowserRemoteness(aBrowser, false);
let currentRemoteType = aBrowser.getAttribute("remoteType") || null;
@@ -1735,29 +1735,29 @@ class TabBrowser {
// correct type.
if (currentRemoteType != aOptions.remoteType ||
aOptions.newFrameloader) {
let remote = aOptions.remoteType != E10SUtils.NOT_REMOTE;
return this.updateBrowserRemoteness(aBrowser, remote, aOptions);
}
return false;
- }
+ },
removePreloadedBrowser() {
if (!this._isPreloadingEnabled()) {
return;
}
let browser = this._getPreloadedBrowser();
if (browser) {
browser.remove();
}
- }
+ },
_getPreloadedBrowser() {
if (!this._isPreloadingEnabled()) {
return null;
}
// The preloaded browser might be null.
let browser = this._preloadedBrowser;
@@ -1772,25 +1772,25 @@ class TabBrowser {
// in the case that the browser is remote, as remote browsers take
// care of that themselves.
if (browser) {
browser.setAttribute("preloadedState", "consumed");
browser.setAttribute("autocompletepopup", "PopupAutoComplete");
}
return browser;
- }
+ },
_isPreloadingEnabled() {
// Preloading for the newtab page is enabled when the pref is true
// and the URL is "about:newtab". We do not support preloading for
// custom newtab URLs.
return Services.prefs.getBoolPref("browser.newtab.preload") &&
!aboutNewTabService.overridden;
- }
+ },
_createPreloadBrowser() {
// Do nothing if we have a preloaded browser already
// or preloading of newtab pages is disabled.
if (this._preloadedBrowser || !this._isPreloadingEnabled()) {
return;
}
@@ -1811,17 +1811,17 @@ class TabBrowser {
}
browser.loadURI(BROWSER_NEW_TAB_URL);
browser.docShellIsActive = false;
// Make sure the preloaded browser is loaded with desired zoom level
let tabURI = Services.io.newURI(BROWSER_NEW_TAB_URL);
FullZoom.onLocationChange(tabURI, false, browser);
- }
+ },
_createBrowser(aParams) {
// Supported parameters:
// userContextId, remote, remoteType, isPreloadBrowser,
// uriIsAboutBlank, sameProcessAsFrameLoader
let b = document.createElementNS(this._XUL_NS, "browser");
b.permanentKey = {};
@@ -1927,17 +1927,17 @@ class TabBrowser {
// Prevent the superfluous initial load of a blank document
// if we're going to load something other than about:blank.
if (!aParams.uriIsAboutBlank) {
b.setAttribute("nodefaultsrc", "true");
}
return b;
- }
+ },
_createLazyBrowser(aTab) {
let browser = aTab.linkedBrowser;
let names = this._browserBindingProperties;
for (let i = 0; i < names.length; i++) {
let name = names[i];
@@ -2021,17 +2021,17 @@ class TabBrowser {
}
Object.defineProperty(browser, name, {
get: getter,
set: setter,
configurable: true,
enumerable: true
});
}
- }
+ },
_insertBrowser(aTab, aInsertedOnTabCreation) {
"use strict";
// If browser is already inserted or window is closed don't do anything.
if (aTab.linkedPanel || window.closed) {
return;
}
@@ -2085,17 +2085,17 @@ class TabBrowser {
// into the DOM. We thus have to register the new outerWindowID
// for non-remote browsers after we have called browser.loadURI().
if (remoteType == E10SUtils.NOT_REMOTE) {
this._outerWindowIDBrowserMap.set(browser.outerWindowID, browser);
}
var evt = new CustomEvent("TabBrowserInserted", { bubbles: true, detail: { insertedOnTabCreation: aInsertedOnTabCreation } });
aTab.dispatchEvent(evt);
- }
+ },
discardBrowser(aBrowser, aForceDiscard) {
"use strict";
let tab = this.getTabForBrowser(aBrowser);
let permitUnloadFlags = aForceDiscard ? aBrowser.dontPromptAndUnload : aBrowser.dontPromptAndDontUnload;
@@ -2144,17 +2144,17 @@ class TabBrowser {
let notificationbox = this.getNotificationBox(aBrowser);
this.mPanelContainer.removeChild(notificationbox);
tab.removeAttribute("linkedpanel");
this._createLazyBrowser(tab);
let evt = new CustomEvent("TabBrowserDiscarded", { bubbles: true });
tab.dispatchEvent(evt);
- }
+ },
// eslint-disable-next-line complexity
addTab(aURI, aReferrerURI, aCharset, aPostData, aOwner, aAllowThirdPartyFixup) {
"use strict";
var aTriggeringPrincipal;
var aReferrerPolicy;
var aFromExternal;
@@ -2481,17 +2481,17 @@ class TabBrowser {
if (animate) {
requestAnimationFrame(function() {
// kick the animation off
t.setAttribute("fadein", "true");
});
}
return t;
- }
+ },
warnAboutClosingTabs(aCloseTabs, aTab) {
var tabsToClose;
switch (aCloseTabs) {
case this.closingTabsEnum.ALL:
tabsToClose = this.tabs.length - this._removingTabs.length -
gBrowser._numPinnedTabs;
break;
@@ -2544,29 +2544,29 @@ class TabBrowser {
warnOnClose);
var reallyClose = (buttonPressed == 0);
// don't set the pref unless they press OK and it's false
if (aCloseTabs == this.closingTabsEnum.ALL && reallyClose && !warnOnClose.value)
Services.prefs.setBoolPref(pref, false);
return reallyClose;
- }
+ },
getTabsToTheEndFrom(aTab) {
let tabsToEnd = [];
let tabs = this.visibleTabs;
for (let i = tabs.length - 1; i >= 0; --i) {
if (tabs[i] == aTab || tabs[i].pinned) {
break;
}
tabsToEnd.push(tabs[i]);
}
return tabsToEnd;
- }
+ },
removeTabsToTheEndFrom(aTab, aParams) {
if (!this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab))
return;
let removeTab = tab => {
// Avoid changing the selected browser several times.
if (tab.selected)
@@ -2580,17 +2580,17 @@ class TabBrowser {
for (let i = tabs.length - 1; i >= 0; --i) {
let tab = tabs[i];
if (this._hasBeforeUnload(tab))
tabsWithBeforeUnload.push(tab);
else
removeTab(tab);
}
tabsWithBeforeUnload.forEach(removeTab);
- }
+ },
removeAllTabsBut(aTab) {
if (!this.warnAboutClosingTabs(this.closingTabsEnum.OTHER)) {
return;
}
let tabs = this.visibleTabs.reverse();
this.selectedTab = aTab;
@@ -2603,21 +2603,21 @@ class TabBrowser {
tabsWithBeforeUnload.push(tab);
else
this.removeTab(tab, { animate: true });
}
}
for (let tab of tabsWithBeforeUnload) {
this.removeTab(tab, { animate: true });
}
- }
+ },
removeCurrentTab(aParams) {
this.removeTab(this.mCurrentTab, aParams);
- }
+ },
removeTab(aTab, aParams) {
if (aParams) {
var animate = aParams.animate;
var byMouse = aParams.byMouse;
var skipPermitUnload = aParams.skipPermitUnload;
}
@@ -2676,24 +2676,24 @@ class TabBrowser {
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);
- }
+ },
_hasBeforeUnload(aTab) {
let browser = aTab.linkedBrowser;
return browser.isRemoteBrowser && browser.frameLoader &&
browser.frameLoader.tabParent &&
browser.frameLoader.tabParent.hasBeforeUnload;
- }
+ },
_beginRemoveTab(aTab, aAdoptedByTab, aCloseWindowWithLastTab, aCloseWindowFastpath, aSkipPermitUnload) {
if (aTab.closing ||
this._windowIsClosing)
return false;
var browser = this.getBrowserForTab(aTab);
if (!aSkipPermitUnload && !aAdoptedByTab &&
@@ -2823,17 +2823,17 @@ class TabBrowser {
// Remove this tab as the owner of any other tabs, since it's going away.
for (let tab of this.tabs) {
if ("owner" in tab && tab.owner == aTab)
// |tab| is a child of the tab we're removing, make it an orphan
tab.owner = null;
}
return true;
- }
+ },
_endRemoveTab(aTab) {
if (!aTab || !aTab._endRemoveArgs)
return;
var [aCloseWindow, aNewTab] = aTab._endRemoveArgs;
aTab._endRemoveArgs = null;
@@ -2943,17 +2943,17 @@ class TabBrowser {
// stopwatches here instead.
TelemetryStopwatch.finish("FX_TAB_CLOSE_TIME_ANIM_MS", aTab,
true /* aCanceledOkay */ );
TelemetryStopwatch.finish("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab,
true /* aCanceledOkay */ );
if (aCloseWindow)
this._windowIsClosing = closeWindow(true, window.warnAboutClosingWindow);
- }
+ },
_findTabToBlurTo(aTab) {
if (!aTab.selected) {
return null;
}
if (aTab.owner &&
!aTab.owner.hidden &&
@@ -2981,21 +2981,21 @@ class TabBrowser {
tab = aTab;
do {
tab = tab.previousSibling;
} while (tab && !remainingTabs.includes(tab));
}
return tab;
- }
+ },
_blurTab(aTab) {
this.selectedTab = this._findTabToBlurTo(aTab);
- }
+ },
swapBrowsersAndCloseOther(aOurTab, aOtherTab) {
// Do not allow transfering a private tab to a non-private window
// and vice versa.
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
PrivateBrowsingUtils.isWindowPrivate(aOtherTab.ownerGlobal))
return;
@@ -3128,17 +3128,17 @@ class TabBrowser {
// If the tab was already selected (this happpens in the scenario
// of replaceTabWithWindow), notify onLocationChange, etc.
if (aOurTab.selected)
this.updateCurrentBrowser(true);
if (modifiedAttrs.length) {
this._tabAttrModified(aOurTab, modifiedAttrs);
}
- }
+ },
swapBrowsers(aOurTab, aOtherTab, aFlags) {
let otherBrowser = aOtherTab.linkedBrowser;
let otherTabBrowser = otherBrowser.getTabBrowser();
// We aren't closing the other tab so, we also need to swap its tablisteners.
let filter = otherTabBrowser._tabFilters.get(aOtherTab);
let tabListener = otherTabBrowser._tabListeners.get(aOtherTab);
@@ -3150,17 +3150,17 @@ class TabBrowser {
// Restore the listeners for the swapped in tab.
tabListener = new otherTabBrowser.ownerGlobal.TabProgressListener(aOtherTab, otherBrowser, false, false);
otherTabBrowser._tabListeners.set(aOtherTab, tabListener);
const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
filter.addProgressListener(tabListener, notifyAll);
otherBrowser.webProgress.addProgressListener(filter, notifyAll);
- }
+ },
_swapBrowserDocShells(aOurTab, aOtherBrowser, aFlags, aStateFlags) {
// aOurTab's browser needs to be inserted now if it hasn't already.
this._insertBrowser(aOurTab);
// Unhook our progress listener
const filter = this._tabFilters.get(aOurTab);
let tabListener = this._tabListeners.get(aOurTab);
@@ -3216,106 +3216,106 @@ class TabBrowser {
// Restore the progress listener
tabListener = new TabProgressListener(aOurTab, ourBrowser, false, false, aStateFlags);
this._tabListeners.set(aOurTab, tabListener);
const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
filter.addProgressListener(tabListener, notifyAll);
ourBrowser.webProgress.addProgressListener(filter, notifyAll);
- }
+ },
_swapRegisteredOpenURIs(aOurBrowser, aOtherBrowser) {
// Swap the registeredOpenURI properties of the two browsers
let tmp = aOurBrowser.registeredOpenURI;
delete aOurBrowser.registeredOpenURI;
if (aOtherBrowser.registeredOpenURI) {
aOurBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
delete aOtherBrowser.registeredOpenURI;
}
if (tmp) {
aOtherBrowser.registeredOpenURI = tmp;
}
- }
+ },
reloadAllTabs() {
let tabs = this.visibleTabs;
let l = tabs.length;
for (var i = 0; i < l; i++) {
try {
this.getBrowserForTab(tabs[i]).reload();
} catch (e) {
// ignore failure to reload so others will be reloaded
}
}
- }
+ },
reloadTab(aTab) {
let browser = this.getBrowserForTab(aTab);
// Reset temporary permissions on the current tab. This is done here
// because we only want to reset permissions on user reload.
SitePermissions.clearTemporaryPermissions(browser);
browser.reload();
- }
+ },
addProgressListener(aListener) {
if (arguments.length != 1) {
Cu.reportError("gBrowser.addProgressListener was " +
"called with a second argument, " +
"which is not supported. See bug " +
"608628. Call stack: " + new Error().stack);
}
this.mProgressListeners.push(aListener);
- }
+ },
removeProgressListener(aListener) {
this.mProgressListeners =
this.mProgressListeners.filter(l => l != aListener);
- }
+ },
addTabsProgressListener(aListener) {
this.mTabsProgressListeners.push(aListener);
- }
+ },
removeTabsProgressListener(aListener) {
this.mTabsProgressListeners =
this.mTabsProgressListeners.filter(l => l != aListener);
- }
+ },
getBrowserForTab(aTab) {
return aTab.linkedBrowser;
- }
+ },
showOnlyTheseTabs(aTabs) {
for (let tab of this.tabs) {
if (!aTabs.includes(tab))
this.hideTab(tab);
else
this.showTab(tab);
}
this.tabContainer._handleTabSelect(true);
- }
+ },
showTab(aTab) {
if (aTab.hidden) {
aTab.removeAttribute("hidden");
this._visibleTabs = null; // invalidate cache
this.tabContainer._updateCloseButtons();
this.tabContainer._setPositionalAttributes();
let event = document.createEvent("Events");
event.initEvent("TabShow", true, false);
aTab.dispatchEvent(event);
SessionStore.deleteTabValue(aTab, "hiddenBy");
}
- }
+ },
hideTab(aTab, aSource) {
if (!aTab.hidden && !aTab.pinned && !aTab.selected &&
!aTab.closing && !aTab._sharingState) {
aTab.setAttribute("hidden", "true");
this._visibleTabs = null; // invalidate cache
this.tabContainer._updateCloseButtons();
@@ -3324,17 +3324,17 @@ class TabBrowser {
let event = document.createEvent("Events");
event.initEvent("TabHide", true, false);
aTab.dispatchEvent(event);
if (aSource) {
SessionStore.setTabValue(aTab, "hiddenBy", aSource);
}
}
- }
+ },
selectTabAtIndex(aIndex, aEvent) {
let tabs = this.visibleTabs;
// count backwards for aIndex < 0
if (aIndex < 0) {
aIndex += tabs.length;
// clamp at index 0 if still negative.
@@ -3346,17 +3346,17 @@ class TabBrowser {
}
this.selectedTab = tabs[aIndex];
if (aEvent) {
aEvent.preventDefault();
aEvent.stopPropagation();
}
- }
+ },
/**
* 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.
*/
replaceTabWithWindow(aTab, aOptions) {
if (this.tabs.length == 1)
return null;
@@ -3370,17 +3370,17 @@ class TabBrowser {
// content area when the docshells are swapped.
if (this.animationsEnabled) {
aTab.style.maxWidth = ""; // ensure that fade-out transition happens
aTab.removeAttribute("fadein");
}
// tell a new window to take the "dropped" tab
return window.openDialog(getBrowserURL(), "_blank", options, aTab);
- }
+ },
moveTabTo(aTab, aIndex, aKeepRelatedTabs) {
var oldPosition = aTab._tPos;
if (oldPosition == aIndex)
return;
// Don't allow mixing pinned and unpinned tabs.
if (aTab.pinned)
@@ -3435,28 +3435,28 @@ class TabBrowser {
if (aTab.pinned)
this.tabContainer._positionPinnedTabs();
this.tabContainer._setPositionalAttributes();
var evt = document.createEvent("UIEvents");
evt.initUIEvent("TabMove", true, false, window, oldPosition);
aTab.dispatchEvent(evt);
- }
+ },
moveTabForward() {
let nextTab = this.mCurrentTab.nextSibling;
while (nextTab && nextTab.hidden)
nextTab = nextTab.nextSibling;
if (nextTab)
this.moveTabTo(this.mCurrentTab, nextTab._tPos);
else if (this.arrowKeysShouldWrap)
this.moveTabToStart();
- }
+ },
/**
* Adopts a tab from another browser window, and inserts it at aIndex
*/
adoptTab(aTab, aIndex, aSelectTab) {
// 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). We also ensure that the tab we create to swap into has
@@ -3502,102 +3502,102 @@ class TabBrowser {
if (aSelectTab) {
// Call updateCurrentBrowser to make sure the URL bar is up to date
// for our new tab after we've done swapBrowsersAndCloseOther.
this.updateCurrentBrowser(true);
}
return newTab;
- }
+ },
moveTabBackward() {
let previousTab = this.mCurrentTab.previousSibling;
while (previousTab && previousTab.hidden)
previousTab = previousTab.previousSibling;
if (previousTab)
this.moveTabTo(this.mCurrentTab, previousTab._tPos);
else if (this.arrowKeysShouldWrap)
this.moveTabToEnd();
- }
+ },
moveTabToStart() {
var tabPos = this.mCurrentTab._tPos;
if (tabPos > 0)
this.moveTabTo(this.mCurrentTab, 0);
- }
+ },
moveTabToEnd() {
var tabPos = this.mCurrentTab._tPos;
if (tabPos < this.browsers.length - 1)
this.moveTabTo(this.mCurrentTab, this.browsers.length - 1);
- }
+ },
moveTabOver(aEvent) {
let direction = window.getComputedStyle(document.documentElement).direction;
if ((direction == "ltr" && aEvent.keyCode == KeyEvent.DOM_VK_RIGHT) ||
(direction == "rtl" && aEvent.keyCode == KeyEvent.DOM_VK_LEFT)) {
this.moveTabForward();
} else {
this.moveTabBackward();
}
- }
+ },
/**
* @param aTab
* Can be from a different window as well
* @param aRestoreTabImmediately
* Can defer loading of the tab contents
*/
duplicateTab(aTab, aRestoreTabImmediately) {
return SessionStore.duplicateTab(window, aTab, 0, aRestoreTabImmediately);
- }
+ },
activateBrowserForPrintPreview(aBrowser) {
this._printPreviewBrowsers.add(aBrowser);
if (this._switcher) {
this._switcher.activateBrowserForPrintPreview(aBrowser);
}
aBrowser.docShellIsActive = true;
- }
+ },
deactivatePrintPreviewBrowsers() {
let browsers = this._printPreviewBrowsers;
this._printPreviewBrowsers = new Set();
for (let browser of browsers) {
browser.docShellIsActive = this.shouldActivateDocShell(browser);
}
- }
+ },
/**
* Returns true if a given browser's docshell should be active.
*/
shouldActivateDocShell(aBrowser) {
if (this._switcher) {
return this._switcher.shouldActivateDocShell(aBrowser);
}
return (aBrowser == this.selectedBrowser &&
window.windowState != window.STATE_MINIMIZED &&
!window.isFullyOccluded) ||
this._printPreviewBrowsers.has(aBrowser);
- }
+ },
_getSwitcher() {
if (!this._switcher) {
this._switcher = new this.AsyncTabSwitcher(this);
}
return this._switcher;
- }
+ },
warmupTab(aTab) {
if (gMultiProcessBrowser) {
this._getSwitcher().warmupTab(aTab);
}
- }
+ },
_handleKeyDownEvent(aEvent) {
if (!aEvent.isTrusted) {
// Don't let untrusted events mess with tabs.
return;
}
if (aEvent.altKey)
@@ -3622,17 +3622,17 @@ class TabBrowser {
if (AppConstants.platform != "macosx") {
if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
!this.mCurrentTab.pinned) {
this.removeCurrentTab({ animate: true });
aEvent.preventDefault();
}
}
- }
+ },
_handleKeyPressEventMac(aEvent) {
if (!aEvent.isTrusted) {
// Don't let untrusted events mess with tabs.
return;
}
if (aEvent.altKey)
@@ -3648,17 +3648,17 @@ class TabBrowser {
offset = -1;
case "{".charCodeAt(0):
if (window.getComputedStyle(document.documentElement).direction == "ltr")
offset *= -1;
this.tabContainer.advanceSelectedTab(offset, true);
aEvent.preventDefault();
}
}
- }
+ },
createTooltip(event) {
event.stopPropagation();
var tab = document.tooltipNode;
if (tab.localName != "tab") {
event.preventDefault();
return;
}
@@ -3701,17 +3701,17 @@ class TabBrowser {
label += " (pid " + tab.linkedBrowser.frameLoader.tabParent.osPid + ")";
}
if (tab.userContextId) {
label = gTabBrowserBundle.formatStringFromName("tabs.containers.tooltip", [label, ContextualIdentityService.getUserContextLabel(tab.userContextId)], 2);
}
}
event.target.setAttribute("label", label);
- }
+ },
handleEvent(aEvent) {
switch (aEvent.type) {
case "keydown":
this._handleKeyDownEvent(aEvent);
break;
case "keypress":
this._handleKeyPressEventMac(aEvent);
@@ -3720,17 +3720,17 @@ class TabBrowser {
case "occlusionstatechange":
if (aEvent.target == window && !this._switcher) {
this.mCurrentBrowser.preserveLayers(
window.windowState == window.STATE_MINIMIZED || window.isFullyOccluded);
this.mCurrentBrowser.docShellIsActive = this.shouldActivateDocShell(this.mCurrentBrowser);
}
break;
}
- }
+ },
receiveMessage(aMessage) {
let data = aMessage.data;
let browser = aMessage.target;
switch (aMessage.name) {
case "DOMTitleChanged":
{
@@ -3872,17 +3872,17 @@ class TabBrowser {
"chrome://browser/skin/notification-icons/popup.svg",
notificationBox.PRIORITY_INFO_MEDIUM,
buttons);
}
break;
}
}
return undefined;
- }
+ },
observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "contextual-identity-updated":
{
for (let tab of this.tabs) {
if (tab.getAttribute("usercontextid") == aData) {
ContextualIdentityService.setTabStyle(tab);
@@ -3892,17 +3892,17 @@ class TabBrowser {
}
case "nsPref:changed":
{
// This is the only pref observed.
this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
break;
}
}
- }
+ },
_updateNewTabVisibility() {
// Helper functions to help deal with customize mode wrapping some items
let wrap = n => n.parentNode.localName == "toolbarpaletteitem" ? n.parentNode : n;
let unwrap = n => n && n.localName == "toolbarpaletteitem" ? n.firstElementChild : n;
let sib = this.tabContainer;
do {
@@ -3910,50 +3910,50 @@ class TabBrowser {
} while (sib && sib.hidden);
const kAttr = "hasadjacentnewtabbutton";
if (sib && sib.id == "new-tab-button") {
this.tabContainer.setAttribute(kAttr, "true");
} else {
this.tabContainer.removeAttribute(kAttr);
}
- }
+ },
onWidgetAfterDOMChange(aNode, aNextNode, aContainer) {
if (aContainer.ownerDocument == document &&
aContainer.id == "TabsToolbar") {
this._updateNewTabVisibility();
}
- }
+ },
onAreaNodeRegistered(aArea, aContainer) {
if (aContainer.ownerDocument == document &&
aArea == "TabsToolbar") {
this._updateNewTabVisibility();
}
- }
+ },
onAreaReset(aArea, aContainer) {
this.onAreaNodeRegistered(aArea, aContainer);
- }
+ },
_generateUniquePanelID() {
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);
- }
+ },
destroy() {
Services.obs.removeObserver(this, "contextual-identity-updated");
CustomizableUI.removeListener(this);
for (let tab of this.tabs) {
let browser = tab.linkedBrowser;
@@ -3994,17 +3994,17 @@ class TabBrowser {
window.messageManager.removeMessageListener("contextmenu", this);
if (this._switcher) {
this._switcher.destroy();
}
}
Services.prefs.removeObserver("accessibility.typeaheadfind", this);
- }
+ },
_setupEventListeners() {
this.addEventListener("DOMWindowClose", (event) => {
if (!event.isTrusted)
return;
if (this.tabs.length == 1) {
// We already did PermitUnload in nsGlobalWindow::Close
@@ -4202,18 +4202,18 @@ class TabBrowser {
if (tab.hasAttribute("activemedia-blocked")) {
tab.removeAttribute("activemedia-blocked");
this._tabAttrModified(tab, ["activemedia-blocked"]);
let hist = Services.telemetry.getHistogramById("TAB_AUDIO_INDICATOR_USED");
hist.add(2 /* unblockByVisitingTab */ );
tab.finishMediaBlockTimer();
}
});
- }
-}
+ },
+};
/**
* A web progress listener object definition for a given tab.
*/
class TabProgressListener {
constructor(aTab, aBrowser, aStartsBlank, aWasPreloadedBrowser, aOrigStateFlags) {
let stateFlags = aOrigStateFlags || 0;
// Initialize mStateFlags to non-zero e.g. when creating a progress