tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TaskbarTabs.sys.mjs (5580B)


      1 /* vim: se cin sw=2 ts=2 et filetype=javascript :
      2 * This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 /**
      7 * This file represents the entry point into the Taskbar Tabs system,
      8 * initializing necessary subsystems before the export can be used. Code driving
      9 * the Taskbar Tabs systems should interact with it through this interface.
     10 */
     11 
     12 import {
     13  TaskbarTabsRegistry,
     14  TaskbarTabsRegistryStorage,
     15  kTaskbarTabsRegistryEvents,
     16 } from "resource:///modules/taskbartabs/TaskbarTabsRegistry.sys.mjs";
     17 import { TaskbarTabsWindowManager } from "resource:///modules/taskbartabs/TaskbarTabsWindowManager.sys.mjs";
     18 import { TaskbarTabsPin } from "resource:///modules/taskbartabs/TaskbarTabsPin.sys.mjs";
     19 import { TaskbarTabsUtils } from "resource:///modules/taskbartabs/TaskbarTabsUtils.sys.mjs";
     20 
     21 let lazy = {};
     22 
     23 ChromeUtils.defineESModuleGetters(lazy, {
     24  ManifestObtainer: "resource://gre/modules/ManifestObtainer.sys.mjs",
     25 });
     26 
     27 ChromeUtils.defineLazyGetter(lazy, "logConsole", () => {
     28  return console.createInstance({
     29    prefix: "TaskbarTabs",
     30    maxLogLevel: "Warn",
     31  });
     32 });
     33 
     34 /**
     35 * A Taskbar Tabs singleton which ensures the system has been initialized before
     36 * it can be interacted with. Methods on this object pass through to the Taskbar
     37 * Tabs registry or window manager.
     38 */
     39 export const TaskbarTabs = new (class {
     40  #ready;
     41  #registry;
     42  #windowManager;
     43 
     44  constructor() {
     45    this.#ready = initRegistry().then(registry => {
     46      this.#registry = registry;
     47      this.#windowManager = initWindowManager(registry);
     48 
     49      this.#updateMetrics();
     50    });
     51  }
     52 
     53  #updateMetrics() {
     54    Glean.webApp.installedWebAppCount.set(this.#registry.countTaskbarTabs());
     55  }
     56 
     57  async waitUntilReady() {
     58    await this.#ready;
     59  }
     60 
     61  async getTaskbarTab(...args) {
     62    await this.#ready;
     63    return this.#registry.getTaskbarTab(...args);
     64  }
     65 
     66  async findOrCreateTaskbarTab(...args) {
     67    await this.#ready;
     68    let result = this.#registry.findOrCreateTaskbarTab(...args);
     69 
     70    if (result.created) {
     71      this.#updateMetrics();
     72 
     73      // Don't wait for the pinning to complete.
     74      TaskbarTabsPin.pinTaskbarTab(result.taskbarTab, this.#registry);
     75    }
     76 
     77    return result;
     78  }
     79 
     80  async findTaskbarTab(...args) {
     81    await this.#ready;
     82    return this.#registry.findTaskbarTab(...args);
     83  }
     84 
     85  /**
     86   * Moves an existing tab into a new Taskbar Tab window.
     87   *
     88   * If there is already a Taskbar Tab for the tab's selected URL and container,
     89   * opens the existing Taskbar Tab. If not, a new Taskbar Tab is created.
     90   *
     91   * @param {MozTabbrowserTab} aTab - The tab to move into a Taskbar Tab window.
     92   * @returns {{window: DOMWindow, taskbarTab: TaskbarTab}} The created window
     93   * and the Taskbar Tab it is associated with.
     94   */
     95  async moveTabIntoTaskbarTab(aTab) {
     96    const browser = aTab.linkedBrowser;
     97    let url = browser.currentURI;
     98    let userContextId = aTab.userContextId;
     99 
    100    let [, manifest] = await Promise.all([
    101      this.#ready,
    102      lazy.ManifestObtainer.browserObtainManifest(browser).catch(e => {
    103        lazy.logConsole.error(e);
    104        return {};
    105      }),
    106    ]);
    107 
    108    let { taskbarTab } = await this.findOrCreateTaskbarTab(
    109      url,
    110      userContextId,
    111      // 'manifest' can be null if the site doesn't have a manifest.
    112      manifest ? { manifest } : {}
    113    );
    114 
    115    let win = await this.replaceTabWithWindow(taskbarTab, aTab);
    116    return {
    117      window: win,
    118      taskbarTab,
    119    };
    120  }
    121 
    122  async resetForTests(...args) {
    123    await this.#ready;
    124    return this.#registry.resetForTests(...args);
    125  }
    126 
    127  async removeTaskbarTab(...args) {
    128    await this.#ready;
    129 
    130    let taskbarTab = this.#registry.removeTaskbarTab(...args);
    131    this.#updateMetrics();
    132 
    133    // Don't wait for unpinning to finish.
    134    TaskbarTabsPin.unpinTaskbarTab(taskbarTab, this.#registry);
    135  }
    136 
    137  async openWindow(...args) {
    138    await this.#ready;
    139    return this.#windowManager.openWindow(...args);
    140  }
    141 
    142  async replaceTabWithWindow(...args) {
    143    await this.#ready;
    144    return this.#windowManager.replaceTabWithWindow(...args);
    145  }
    146 
    147  async ejectWindow(...args) {
    148    await this.#ready;
    149    return this.#windowManager.ejectWindow(...args);
    150  }
    151 
    152  async getCountForId(...args) {
    153    await this.#ready;
    154    return this.#windowManager.getCountForId(...args);
    155  }
    156 })();
    157 
    158 /**
    159 * Taskbar Tabs Registry initialization.
    160 *
    161 * @returns {TaskbarTabsRegistry} A registry after loading and hooking saving to persistent storage.
    162 */
    163 async function initRegistry() {
    164  const kRegistryFilename = "taskbartabs.json";
    165  // Construct the path [Profile]/taskbartabs/taskbartabs.json.
    166  let registryFile = TaskbarTabsUtils.getTaskbarTabsFolder();
    167  registryFile.append(kRegistryFilename);
    168 
    169  let init = {};
    170  if (registryFile.exists()) {
    171    init.loadFile = registryFile;
    172  }
    173 
    174  let registry = await TaskbarTabsRegistry.create(init);
    175 
    176  // Initialize persistent storage.
    177  let storage = new TaskbarTabsRegistryStorage(registry, registryFile);
    178  registry.on(kTaskbarTabsRegistryEvents.created, () => {
    179    storage.save();
    180  });
    181  registry.on(kTaskbarTabsRegistryEvents.patched, () => {
    182    storage.save();
    183  });
    184  registry.on(kTaskbarTabsRegistryEvents.removed, () => {
    185    storage.save();
    186  });
    187 
    188  return registry;
    189 }
    190 
    191 /**
    192 * Taskbar Tabs Window Manager initialization.
    193 *
    194 * @returns {TaskbarTabsWindowManager} The initialized Window Manager
    195 */
    196 function initWindowManager() {
    197  let wm = new TaskbarTabsWindowManager();
    198 
    199  return wm;
    200 }