forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			206 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 | 
						|
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
// This file is loaded into the browser window scope.
 | 
						|
/* eslint-env mozilla/browser-window */
 | 
						|
 | 
						|
ChromeUtils.defineESModuleGetters(this, {
 | 
						|
  OriginControls: "resource://gre/modules/ExtensionPermissions.sys.mjs",
 | 
						|
});
 | 
						|
 | 
						|
/**
 | 
						|
 * The `unified-extensions-item` custom element is used to manage an extension
 | 
						|
 * in the list of extensions, which is displayed when users click the unified
 | 
						|
 * extensions (toolbar) button.
 | 
						|
 *
 | 
						|
 * This custom element must be initialized with `setExtension()`:
 | 
						|
 *
 | 
						|
 * ```
 | 
						|
 * let item = document.createElement("unified-extensions-item");
 | 
						|
 * item.setExtension(extension);
 | 
						|
 * document.body.appendChild(item);
 | 
						|
 * ```
 | 
						|
 */
 | 
						|
customElements.define(
 | 
						|
  "unified-extensions-item",
 | 
						|
  class extends HTMLElement {
 | 
						|
    /**
 | 
						|
     * Set the extension for this item. The item will be populated based on the
 | 
						|
     * extension when it is rendered into the DOM.
 | 
						|
     *
 | 
						|
     * @param {Extension} extension The extension to use.
 | 
						|
     */
 | 
						|
    setExtension(extension) {
 | 
						|
      this.extension = extension;
 | 
						|
    }
 | 
						|
 | 
						|
    connectedCallback() {
 | 
						|
      if (this._menuButton) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      const template = document.getElementById(
 | 
						|
        "unified-extensions-item-template"
 | 
						|
      );
 | 
						|
      this.appendChild(template.content.cloneNode(true));
 | 
						|
 | 
						|
      this._actionButton = this.querySelector(
 | 
						|
        ".unified-extensions-item-action-button"
 | 
						|
      );
 | 
						|
      this._menuButton = this.querySelector(
 | 
						|
        ".unified-extensions-item-menu-button"
 | 
						|
      );
 | 
						|
      this._messageDeck = this.querySelector(
 | 
						|
        ".unified-extensions-item-message-deck"
 | 
						|
      );
 | 
						|
 | 
						|
      // Focus/blur events are fired on specific elements only.
 | 
						|
      this._actionButton.addEventListener("blur", this);
 | 
						|
      this._actionButton.addEventListener("focus", this);
 | 
						|
      this._menuButton.addEventListener("blur", this);
 | 
						|
      this._menuButton.addEventListener("focus", this);
 | 
						|
 | 
						|
      this.addEventListener("command", this);
 | 
						|
      this.addEventListener("mouseout", this);
 | 
						|
      this.addEventListener("mouseover", this);
 | 
						|
 | 
						|
      this.render();
 | 
						|
    }
 | 
						|
 | 
						|
    handleEvent(event) {
 | 
						|
      const { target } = event;
 | 
						|
 | 
						|
      switch (event.type) {
 | 
						|
        case "command":
 | 
						|
          if (target === this._menuButton) {
 | 
						|
            const popup = target.ownerDocument.getElementById(
 | 
						|
              "unified-extensions-context-menu"
 | 
						|
            );
 | 
						|
            // Anchor to the visible part of the button.
 | 
						|
            const anchor = target.firstElementChild;
 | 
						|
            popup.openPopup(
 | 
						|
              anchor,
 | 
						|
              "after_end",
 | 
						|
              0,
 | 
						|
              0,
 | 
						|
              true /* isContextMenu */,
 | 
						|
              false /* attributesOverride */,
 | 
						|
              event
 | 
						|
            );
 | 
						|
          } else if (target === this._actionButton) {
 | 
						|
            const win = event.target.ownerGlobal;
 | 
						|
            const tab = win.gBrowser.selectedTab;
 | 
						|
 | 
						|
            this.extension.tabManager.addActiveTabPermission(tab);
 | 
						|
            this.extension.tabManager.activateScripts(tab);
 | 
						|
          }
 | 
						|
          break;
 | 
						|
 | 
						|
        case "blur":
 | 
						|
        case "mouseout":
 | 
						|
          this._messageDeck.selectedIndex =
 | 
						|
            gUnifiedExtensions.MESSAGE_DECK_INDEX_DEFAULT;
 | 
						|
          break;
 | 
						|
 | 
						|
        case "focus":
 | 
						|
        case "mouseover":
 | 
						|
          if (target === this._menuButton) {
 | 
						|
            this._messageDeck.selectedIndex =
 | 
						|
              gUnifiedExtensions.MESSAGE_DECK_INDEX_MENU_HOVER;
 | 
						|
          } else if (target === this._actionButton) {
 | 
						|
            this._messageDeck.selectedIndex =
 | 
						|
              gUnifiedExtensions.MESSAGE_DECK_INDEX_HOVER;
 | 
						|
          }
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    #setStateMessage() {
 | 
						|
      const messages = OriginControls.getStateMessageIDs({
 | 
						|
        policy: this.extension.policy,
 | 
						|
        tab: this.ownerGlobal.gBrowser.selectedTab,
 | 
						|
      });
 | 
						|
 | 
						|
      if (!messages) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      const messageDefaultElement = this.querySelector(
 | 
						|
        ".unified-extensions-item-message-default"
 | 
						|
      );
 | 
						|
      this.ownerDocument.l10n.setAttributes(
 | 
						|
        messageDefaultElement,
 | 
						|
        messages.default
 | 
						|
      );
 | 
						|
 | 
						|
      const messageHoverElement = this.querySelector(
 | 
						|
        ".unified-extensions-item-message-hover"
 | 
						|
      );
 | 
						|
      this.ownerDocument.l10n.setAttributes(
 | 
						|
        messageHoverElement,
 | 
						|
        messages.onHover || messages.default
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    #hasAction() {
 | 
						|
      const state = OriginControls.getState(
 | 
						|
        this.extension.policy,
 | 
						|
        this.ownerGlobal.gBrowser.selectedTab
 | 
						|
      );
 | 
						|
 | 
						|
      return state && state.whenClicked && !state.hasAccess;
 | 
						|
    }
 | 
						|
 | 
						|
    render() {
 | 
						|
      if (!this.extension) {
 | 
						|
        throw new Error(
 | 
						|
          "unified-extensions-item requires an extension, forgot to call setExtension()?"
 | 
						|
        );
 | 
						|
      }
 | 
						|
 | 
						|
      this.setAttribute("extension-id", this.extension.id);
 | 
						|
      this.classList.add(
 | 
						|
        "toolbaritem-combined-buttons",
 | 
						|
        "unified-extensions-item"
 | 
						|
      );
 | 
						|
 | 
						|
      // The data-extensionid attribute is used by context menu handlers
 | 
						|
      // to identify the extension being manipulated by the context menu.
 | 
						|
      this._actionButton.dataset.extensionid = this.extension.id;
 | 
						|
 | 
						|
      const { attention } = OriginControls.getAttentionState(
 | 
						|
        this.extension.policy,
 | 
						|
        this.ownerGlobal
 | 
						|
      );
 | 
						|
      this.toggleAttribute("attention", attention);
 | 
						|
 | 
						|
      this.querySelector(".unified-extensions-item-name").textContent =
 | 
						|
        this.extension.name;
 | 
						|
 | 
						|
      AddonManager.getAddonByID(this.extension.id).then(addon => {
 | 
						|
        const iconURL = AddonManager.getPreferredIconURL(addon, 32, window);
 | 
						|
        if (iconURL) {
 | 
						|
          this.querySelector(".unified-extensions-item-icon").setAttribute(
 | 
						|
            "src",
 | 
						|
            iconURL
 | 
						|
          );
 | 
						|
        }
 | 
						|
      });
 | 
						|
 | 
						|
      this._actionButton.disabled = !this.#hasAction();
 | 
						|
 | 
						|
      // The data-extensionid attribute is used by context menu handlers
 | 
						|
      // to identify the extension being manipulated by the context menu.
 | 
						|
      this._menuButton.dataset.extensionid = this.extension.id;
 | 
						|
      this.ownerDocument.l10n.setAttributes(
 | 
						|
        this._menuButton,
 | 
						|
        "unified-extensions-item-open-menu",
 | 
						|
        { extensionName: this.extension.name }
 | 
						|
      );
 | 
						|
 | 
						|
      this.#setStateMessage();
 | 
						|
    }
 | 
						|
  }
 | 
						|
);
 |