Bug 1752140 [wpt PR 32556] - battery status: Remove battery-insecure-context.html...
[gecko.git] / remote / shared / TabManager.jsm
blob0f4b1e1f906112847f0b3add16f8cf9056ae8f2f
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 "use strict";
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",
17 });
19 // Maps browser's permanentKey to uuid: WeakMap.<Object, string>
20 const browserUniqueIds = new WeakMap();
22 var TabManager = {
23   /**
24    * Retrieve all the browser elements from tabs as contained in open windows.
25    *
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.
29    */
30   browsers() {
31     const browsers = [];
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);
39         });
40         browsers.push(...contentBrowsers);
41       }
42     }
44     return browsers;
45   },
47   get windows() {
48     return Services.wm.getEnumerator(null);
49   },
51   /**
52    * Array of unique browser ids (UUIDs) for all content browsers of all
53    * windows.
54    *
55    * TODO: Similarly to getBrowserById, we should improve the performance of
56    * this getter in Bug 1750065.
57    *
58    * @return {Array<String>}
59    *     Array of UUIDs for all content browsers.
60    */
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);
72           if (winId !== null) {
73             browserIds.push(winId);
74           }
75         }
76       }
77     }
79     return browserIds;
80   },
82   /**
83    * Get the <code>&lt;xul:browser&gt;</code> for the specified tab.
84    *
85    * @param {Tab} tab
86    *     The tab whose browser needs to be returned.
87    *
88    * @return {xul:browser}
89    *     The linked browser for the tab or null if no browser can be found.
90    */
91   getBrowserForTab(tab) {
92     if (tab && "linkedBrowser" in tab) {
93       return tab.linkedBrowser;
94     }
96     return null;
97   },
99   /**
100    * Return the tab browser for the specified chrome window.
101    *
102    * @param {ChromeWindow} win
103    *     Window whose <code>tabbrowser</code> needs to be accessed.
104    *
105    * @return {Tab}
106    *     Tab browser or null if it's not a browser window.
107    */
108   getTabBrowser(win) {
109     // GeckoView
110     // TODO: Migrate to AppInfo.isAndroid after AppInfo moves to shared/
111     if (Services.appinfo.OS === "Android") {
112       return new MobileTabBrowser(win);
113       // Firefox
114     } else if ("gBrowser" in win) {
115       return win.gBrowser;
116       // Thunderbird
117     } else if (win.document.getElementById("tabmail")) {
118       return win.document.getElementById("tabmail");
119     }
121     return null;
122   },
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(),
130       userContextId,
131     });
132     this.selectTab(tab);
134     return tab;
135   },
137   /**
138    * Retrieve a the browser element corresponding to the provided unique id,
139    * previously generated via getIdForBrowser.
140    *
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.
144    *
145    * @param {String} id
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.
150    */
151   getBrowserById(id) {
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;
159           }
160         }
161       }
162     }
163     return null;
164   },
166   /**
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.
170    *
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.
174    */
175   getIdForBrowser(browserElement) {
176     if (browserElement === null) {
177       return null;
178     }
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));
184     }
185     return browserUniqueIds.get(key);
186   },
188   /**
189    * Retrieve the unique id for the browser element owning the provided browsing
190    * context.
191    *
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.
195    */
196   getBrowserIdForBrowsingContext(browsingContext) {
197     const contentBrowser = browsingContext.top.embedderElement;
198     return this.getIdForBrowser(contentBrowser);
199   },
201   /**
202    * Retrieve the id of a Browsing Context.
203    *
204    * For a top-level browsing context a custom unique id will be returned.
205    *
206    * @param {BrowsingContext=} browsingContext
207    *     The browsing context to get the id from.
208    *
209    * @returns {String}
210    *     The id of the browsing context.
211    */
212   getIdForBrowsingContext(browsingContext) {
213     if (!browsingContext) {
214       return null;
215     }
217     if (!browsingContext.parent) {
218       // Top-level browsing contexts have their own custom unique id.
219       return this.getIdForBrowser(browsingContext.embedderElement);
220     }
222     return browsingContext.id.toString();
223   },
225   getTabCount() {
226     let count = 0;
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;
232       } else {
233         count += 1;
234       }
235     }
236     return count;
237   },
239   removeTab(tab) {
240     const tabBrowser = this.getTabBrowser(tab.ownerGlobal);
241     tabBrowser.removeTab(tab);
242   },
244   selectTab(tab) {
245     const tabBrowser = this.getTabBrowser(tab.ownerGlobal);
246     tabBrowser.selectedTab = tab;
247   },