tor-browser

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

TaskbarTabsPageAction.sys.mjs (5421B)


      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 const kWidgetId = "taskbar-tabs-button";
      7 
      8 import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
      9 
     10 let lazy = {};
     11 
     12 ChromeUtils.defineESModuleGetters(lazy, {
     13  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
     14  TaskbarTabs: "resource:///modules/taskbartabs/TaskbarTabs.sys.mjs",
     15  TaskbarTabsUtils: "resource:///modules/taskbartabs/TaskbarTabsUtils.sys.mjs",
     16 });
     17 
     18 ChromeUtils.defineLazyGetter(lazy, "logConsole", () => {
     19  return console.createInstance({
     20    prefix: "TaskbarTabs",
     21    maxLogLevel: "Warn",
     22  });
     23 });
     24 
     25 /**
     26 * Object which handles Taskbar Tabs page actions.
     27 */
     28 export const TaskbarTabsPageAction = {
     29  // Set of tabs currently being processed due to a page action event.
     30  _processingTabs: new Set(),
     31 
     32  /**
     33   * Connects a listener to the Taskbar Tabs page action.
     34   *
     35   * @param {DOMWindow} aWindow - The browser window.
     36   */
     37  init(aWindow) {
     38    let isPopupWindow = !aWindow.toolbar.visible;
     39    let isPrivate = lazy.PrivateBrowsingUtils.isWindowPrivate(aWindow);
     40    let isWin32 = AppConstants.platform === "win";
     41    let isMsix =
     42      isWin32 && Services.sysinfo.getProperty("hasWinPackageId", false); // Bug 1979190
     43 
     44    if (isPopupWindow || isPrivate || !isWin32 || isMsix) {
     45      lazy.logConsole.info("Not initializing Taskbar Tabs Page Action.");
     46      return;
     47    }
     48 
     49    lazy.logConsole.info("Initializing Taskbar Tabs Page Action.");
     50 
     51    let taskbarTabsButton = aWindow.document.getElementById(kWidgetId);
     52    taskbarTabsButton.addEventListener("click", this, true);
     53 
     54    if (lazy.TaskbarTabsUtils.isTaskbarTabWindow(aWindow)) {
     55      taskbarTabsButton.setAttribute(
     56        "data-l10n-id",
     57        "taskbar-tab-urlbar-button-close"
     58      );
     59    }
     60 
     61    initVisibilityChanges(aWindow, taskbarTabsButton);
     62  },
     63 
     64  /**
     65   * Handles the clicking of the page action button associated with Taskbar
     66   * Tabs.
     67   *
     68   * @param {Event} aEvent - The event triggered by the Taskbar Tabs page
     69   * action.
     70   * @returns {Promise} Resolves once the event has been handled.
     71   */
     72  async handleEvent(aEvent) {
     73    if (aEvent.button != 0) {
     74      // Only handle left-click events.
     75      return;
     76    }
     77 
     78    let window = aEvent.target.ownerGlobal;
     79    let currentTab = window.gBrowser.selectedTab;
     80 
     81    if (this._processingTabs.has(currentTab)) {
     82      // Button was clicked before last input finished processing for the tab,
     83      // discard to avoid racing. Don't bother buffering input - clicking
     84      // repeatedly before input is processed is not meaningful.
     85      lazy.logConsole.debug(
     86        `Page Action still processing for tab, dropping input.`
     87      );
     88      return;
     89    }
     90    lazy.logConsole.debug(`Blocking Page Action input for tab.`);
     91    this._processingTabs.add(currentTab);
     92 
     93    try {
     94      let isTaskbarTabWindow = lazy.TaskbarTabsUtils.isTaskbarTabWindow(window);
     95 
     96      if (!isTaskbarTabWindow) {
     97        lazy.logConsole.info("Opening new Taskbar Tab via Page Action.");
     98        await lazy.TaskbarTabs.moveTabIntoTaskbarTab(currentTab);
     99      } else {
    100        lazy.logConsole.info("Closing Taskbar Tab via Page Action.");
    101 
    102        // Move tab to a regular browser window.
    103        let id = lazy.TaskbarTabsUtils.getTaskbarTabIdFromWindow(window);
    104 
    105        await lazy.TaskbarTabs.ejectWindow(window);
    106 
    107        if (!(await lazy.TaskbarTabs.getCountForId(id))) {
    108          lazy.logConsole.info("Uninstalling Taskbar Tab via Page Action.");
    109          await lazy.TaskbarTabs.removeTaskbarTab(id);
    110        }
    111      }
    112    } finally {
    113      lazy.logConsole.debug(`Unblocking Page Action input for tab.`);
    114      this._processingTabs.delete(currentTab);
    115    }
    116  },
    117 };
    118 
    119 /**
    120 * Shows or hides the page action as the user navigates.
    121 *
    122 * @param {Window} aWindow - The window that contains the page action.
    123 * @param {Element} aElement - The element that makes up the page action.
    124 */
    125 function initVisibilityChanges(aWindow, aElement) {
    126  // Filled in at the end; memoized to avoid performance failures.
    127  let isTaskbarTabsEnabled = false;
    128 
    129  const shouldHide = aLocation => {
    130    if (!isTaskbarTabsEnabled) {
    131      return true;
    132    }
    133 
    134    // Forcefully initialize Taskbar Tabs. At some point, this will also affect
    135    // the page action; in the meantime, ensures that telemetry info is
    136    // prepared whenever the pref is enabled.
    137    //
    138    // This is a promise, but we don't care when it finishes. It's a no-op if
    139    // TaskbarTabs already initialized.
    140    lazy.TaskbarTabs.waitUntilReady();
    141 
    142    return (
    143      !(aLocation instanceof Ci.nsIURL) && !aLocation.scheme.startsWith("http")
    144    );
    145  };
    146 
    147  aWindow.gBrowser.addProgressListener({
    148    onLocationChange(aWebProgress, aRequest, aLocation) {
    149      if (aWebProgress.isTopLevel) {
    150        aElement.hidden = shouldHide(aLocation);
    151      }
    152    },
    153  });
    154 
    155  const observer = () => {
    156    isTaskbarTabsEnabled = lazy.TaskbarTabsUtils.isEnabled();
    157    aElement.hidden = shouldHide(aWindow.gBrowser.currentURI);
    158  };
    159 
    160  Services.prefs.addObserver("browser.taskbarTabs.enabled", observer);
    161  aWindow.addEventListener("unload", function () {
    162    Services.prefs.removeObserver("browser.taskbarTabs.enabled", observer);
    163  });
    164 
    165  observer();
    166 }