Merge mozilla-central to autoland. a=merge CLOSED TREE
[gecko.git] / browser / base / content / browser-allTabsMenu.js
bloba9caeffca0674837efba1717f6b59810b383ec41
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // This file is loaded into the browser window scope.
6 /* eslint-env mozilla/browser-window */
8 ChromeUtils.defineESModuleGetters(this, {
9   TabsPanel: "resource:///modules/TabsList.sys.mjs",
10 });
12 var gTabsPanel = {
13   kElements: {
14     allTabsButton: "alltabs-button",
15     allTabsView: "allTabsMenu-allTabsView",
16     allTabsViewTabs: "allTabsMenu-allTabsView-tabs",
17     dropIndicator: "allTabsMenu-dropIndicator",
18     containerTabsView: "allTabsMenu-containerTabsView",
19     hiddenTabsButton: "allTabsMenu-hiddenTabsButton",
20     hiddenTabsView: "allTabsMenu-hiddenTabsView",
21   },
22   _initialized: false,
23   _initializedElements: false,
25   initElements() {
26     if (this._initializedElements) {
27       return;
28     }
29     let template = document.getElementById("allTabsMenu-container");
30     template.replaceWith(template.content);
32     for (let [name, id] of Object.entries(this.kElements)) {
33       this[name] = document.getElementById(id);
34     }
35     this._initializedElements = true;
36   },
38   init() {
39     if (this._initialized) {
40       return;
41     }
43     this.initElements();
45     this.hiddenAudioTabsPopup = new TabsPanel({
46       view: this.allTabsView,
47       insertBefore: document.getElementById("allTabsMenu-tabsSeparator"),
48       filterFn: tab => tab.hidden && tab.soundPlaying,
49     });
50     let showPinnedTabs = Services.prefs.getBoolPref(
51       "browser.tabs.tabmanager.enabled"
52     );
53     this.allTabsPanel = new TabsPanel({
54       view: this.allTabsView,
55       containerNode: this.allTabsViewTabs,
56       filterFn: tab =>
57         !tab.hidden && (!tab.pinned || (showPinnedTabs && tab.pinned)),
58       dropIndicator: this.dropIndicator,
59     });
61     this.allTabsView.addEventListener("ViewShowing", () => {
62       PanelUI._ensureShortcutsShown(this.allTabsView);
64       let containersEnabled =
65         Services.prefs.getBoolPref("privacy.userContext.enabled") &&
66         !PrivateBrowsingUtils.isWindowPrivate(window);
67       document.getElementById("allTabsMenu-containerTabsButton").hidden =
68         !containersEnabled;
70       let hasHiddenTabs = gBrowser.visibleTabs.length < gBrowser.tabs.length;
71       document.getElementById("allTabsMenu-hiddenTabsButton").hidden =
72         !hasHiddenTabs;
73       document.getElementById("allTabsMenu-hiddenTabsSeparator").hidden =
74         !hasHiddenTabs;
75     });
77     this.allTabsView.addEventListener("ViewShown", () =>
78       this.allTabsView
79         .querySelector(".all-tabs-item[selected]")
80         ?.scrollIntoView({ block: "center" })
81     );
83     let containerTabsMenuSeparator =
84       this.containerTabsView.querySelector("toolbarseparator");
85     this.containerTabsView.addEventListener("ViewShowing", e => {
86       let elements = [];
87       let frag = document.createDocumentFragment();
89       ContextualIdentityService.getPublicIdentities().forEach(identity => {
90         let menuitem = document.createXULElement("toolbarbutton");
91         menuitem.setAttribute("class", "subviewbutton subviewbutton-iconic");
92         if (identity.name) {
93           menuitem.setAttribute("label", identity.name);
94         } else {
95           document.l10n.setAttributes(menuitem, identity.l10nId);
96         }
97         // The styles depend on this.
98         menuitem.setAttribute("usercontextid", identity.userContextId);
99         // The command handler depends on this.
100         menuitem.setAttribute("data-usercontextid", identity.userContextId);
101         menuitem.classList.add("identity-icon-" + identity.icon);
102         menuitem.classList.add("identity-color-" + identity.color);
104         menuitem.setAttribute("command", "Browser:NewUserContextTab");
106         frag.appendChild(menuitem);
107         elements.push(menuitem);
108       });
110       e.target.addEventListener(
111         "ViewHiding",
112         () => {
113           for (let element of elements) {
114             element.remove();
115           }
116         },
117         { once: true }
118       );
119       containerTabsMenuSeparator.parentNode.insertBefore(
120         frag,
121         containerTabsMenuSeparator
122       );
123     });
125     this.hiddenTabsPopup = new TabsPanel({
126       view: this.hiddenTabsView,
127       filterFn: tab => tab.hidden,
128     });
130     this._initialized = true;
131   },
133   get canOpen() {
134     this.initElements();
135     return isElementVisible(this.allTabsButton);
136   },
138   showAllTabsPanel(event, entrypoint = "unknown") {
139     // Note that event may be null.
141     // Only space and enter should open the popup, ignore other keypresses:
142     if (event?.type == "keypress" && event.key != "Enter" && event.key != " ") {
143       return;
144     }
145     this.init();
146     if (this.canOpen) {
147       Services.telemetry.keyedScalarAdd(
148         "browser.ui.interaction.all_tabs_panel_entrypoint",
149         entrypoint,
150         1
151       );
152       PanelUI.showSubView(
153         this.kElements.allTabsView,
154         this.allTabsButton,
155         event
156       );
157     }
158   },
160   hideAllTabsPanel() {
161     if (this.allTabsView) {
162       PanelMultiView.hidePopup(this.allTabsView.closest("panel"));
163     }
164   },
166   showHiddenTabsPanel(event, entrypoint = "unknown") {
167     this.init();
168     if (!this.canOpen) {
169       return;
170     }
171     this.allTabsView.addEventListener(
172       "ViewShown",
173       () => {
174         PanelUI.showSubView(
175           this.kElements.hiddenTabsView,
176           this.hiddenTabsButton
177         );
178       },
179       { once: true }
180     );
181     this.showAllTabsPanel(event, entrypoint);
182   },
184   searchTabs() {
185     gURLBar.search(UrlbarTokenizer.RESTRICT.OPENPAGE, {
186       searchModeEntry: "tabmenu",
187     });
188   },