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/. */
7 var EXPORTED_SYMBOLS = ["TabManager"];
9 var { XPCOMUtils } = ChromeUtils.import(
10 "resource://gre/modules/XPCOMUtils.jsm"
13 XPCOMUtils.defineLazyModuleGetters(this, {
14 Services: "resource://gre/modules/Services.jsm",
16 MobileTabBrowser: "chrome://remote/content/shared/MobileTabBrowser.jsm",
19 // Maps browser's permanentKey to uuid: WeakMap.<Object, string>
20 const browserUniqueIds = new WeakMap();
24 * Retrieve all the browser elements from tabs as contained in open windows.
26 * @return {Array<xul:browser>}
27 * All the found <xul:browser>s. Will return an empty array if
28 * no windows and tabs can be found.
33 for (const win of this.windows) {
34 const tabBrowser = this.getTabBrowser(win);
36 if (tabBrowser && tabBrowser.tabs) {
37 const contentBrowsers = tabBrowser.tabs.map(tab => {
38 return this.getBrowserForTab(tab);
40 browsers.push(...contentBrowsers);
48 return Services.wm.getEnumerator(null);
52 * Array of unique browser ids (UUIDs) for all content browsers of all
55 * TODO: Similarly to getBrowserById, we should improve the performance of
56 * this getter in Bug 1750065.
58 * @return {Array<String>}
59 * Array of UUIDs for all content browsers.
61 get allBrowserUniqueIds() {
62 const browserIds = [];
64 for (const win of this.windows) {
65 const tabBrowser = this.getTabBrowser(win);
67 // Only return handles for browser windows
68 if (tabBrowser && tabBrowser.tabs) {
69 for (const tab of tabBrowser.tabs) {
70 const contentBrowser = this.getBrowserForTab(tab);
71 const winId = this.getIdForBrowser(contentBrowser);
73 browserIds.push(winId);
83 * Get the <code><xul:browser></code> for the specified tab.
86 * The tab whose browser needs to be returned.
88 * @return {xul:browser}
89 * The linked browser for the tab or null if no browser can be found.
91 getBrowserForTab(tab) {
92 if (tab && "linkedBrowser" in tab) {
93 return tab.linkedBrowser;
100 * Return the tab browser for the specified chrome window.
102 * @param {ChromeWindow} win
103 * Window whose <code>tabbrowser</code> needs to be accessed.
106 * Tab browser or null if it's not a browser window.
110 // TODO: Migrate to AppInfo.isAndroid after AppInfo moves to shared/
111 if (Services.appinfo.OS === "Android") {
112 return new MobileTabBrowser(win);
114 } else if ("gBrowser" in win) {
117 } else if (win.document.getElementById("tabmail")) {
118 return win.document.getElementById("tabmail");
124 addTab({ userContextId }) {
125 const window = Services.wm.getMostRecentWindow(null);
126 const tabBrowser = this.getTabBrowser(window);
128 const tab = tabBrowser.addTab("about:blank", {
129 triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
138 * Retrieve a the browser element corresponding to the provided unique id,
139 * previously generated via getIdForBrowser.
141 * TODO: To avoid creating strong references on browser elements and
142 * potentially leaking those elements, this method loops over all windows and
143 * all tabs. It should be replaced by a faster implementation in Bug 1750065.
146 * A browser unique id created by getIdForBrowser.
147 * @return {xul:browser}
148 * The <xul:browser> corresponding to the provided id. Will return null if
149 * no matching browser element is found.
152 for (const win of this.windows) {
153 const tabBrowser = this.getTabBrowser(win);
154 if (tabBrowser && tabBrowser.tabs) {
155 for (let i = 0; i < tabBrowser.tabs.length; ++i) {
156 const contentBrowser = this.getBrowserForTab(tabBrowser.tabs[i]);
157 if (this.getIdForBrowser(contentBrowser) == id) {
158 return contentBrowser;
167 * Retrieve the unique id for the given xul browser element. The id is a
168 * dynamically generated uuid associated with the permanentKey property of the
169 * given browser element.
171 * @param {xul:browser} browserElement
172 * The <xul:browser> for which we want to retrieve the id.
173 * @return {String} The unique id for this browser.
175 getIdForBrowser(browserElement) {
176 if (browserElement === null) {
180 const key = browserElement.permanentKey;
181 if (!browserUniqueIds.has(key)) {
182 const uuid = Services.uuid.generateUUID().toString();
183 browserUniqueIds.set(key, uuid.substring(1, uuid.length - 1));
185 return browserUniqueIds.get(key);
189 * Retrieve the unique id for the browser element owning the provided browsing
192 * @param {BrowsingContext} browsingContext
193 * The browsing context for which we want to retrieve the (browser) uuid.
194 * @return {String} The unique id for the browser owning the browsing context.
196 getBrowserIdForBrowsingContext(browsingContext) {
197 const contentBrowser = browsingContext.top.embedderElement;
198 return this.getIdForBrowser(contentBrowser);
202 * Retrieve the id of a Browsing Context.
204 * For a top-level browsing context a custom unique id will be returned.
206 * @param {BrowsingContext=} browsingContext
207 * The browsing context to get the id from.
210 * The id of the browsing context.
212 getIdForBrowsingContext(browsingContext) {
213 if (!browsingContext) {
217 if (!browsingContext.parent) {
218 // Top-level browsing contexts have their own custom unique id.
219 return this.getIdForBrowser(browsingContext.embedderElement);
222 return browsingContext.id.toString();
227 for (const win of this.windows) {
228 // For browser windows count the tabs. Otherwise take the window itself.
229 const tabbrowser = this.getTabBrowser(win);
230 if (tabbrowser?.tabs) {
231 count += tabbrowser.tabs.length;
240 const tabBrowser = this.getTabBrowser(tab.ownerGlobal);
241 tabBrowser.removeTab(tab);
245 const tabBrowser = this.getTabBrowser(tab.ownerGlobal);
246 tabBrowser.selectedTab = tab;