Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  context-menu.js   Sprache: JAVA

 
/* 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/. */


"use strict";

const Menu = require("resource://devtools/client/framework/menu.js");
const MenuItem = require("resource://devtools/client/framework/menu-item.js");

const {
  MESSAGE_SOURCE,
} = require("resource://devtools/client/webconsole/constants.js");

const clipboardHelper = require("resource://devtools/shared/platform/clipboard.js");
const {
  l10n,
} = require("resource://devtools/client/webconsole/utils/messages.js");
const actions = require("resource://devtools/client/webconsole/actions/index.js");

loader.lazyRequireGetter(
  this,
  "saveAs",
  "resource://devtools/shared/DevToolsUtils.js",
  true
);
loader.lazyRequireGetter(
  this,
  "openContentLink",
  "resource://devtools/client/shared/link.js",
  true
);
loader.lazyRequireGetter(
  this,
  "getElementText",
  "resource://devtools/client/webconsole/utils/clipboard.js",
  true
);

/**
 * Create a Menu instance for the webconsole.
 *
 * @param {Event} context menu event
 *        {Object} message (optional) message object containing metadata such as:
 *        - {String} source
 *        - {String} request
 * @param {Object} options
 *        - {Actions} bound actions
 *        - {WebConsoleWrapper} wrapper instance used for accessing properties like the store
 *          and window.
 */

function createContextMenu(event, message, webConsoleWrapper) {
  const { target } = event;
  const { parentNode, toolbox, hud } = webConsoleWrapper;
  const store = webConsoleWrapper.getStore();
  const { dispatch } = store;

  const messageEl = target.closest(".message");
  const clipboardText = getElementText(messageEl);

  const linkEl = target.closest("a[href]");
  const url = linkEl && linkEl.href;

  const messageVariable = target.closest(".objectBox");
  // Ensure that console.group and console.groupCollapsed commands are not captured
  const variableText =
    messageVariable &&
    !messageEl.classList.contains("startGroup") &&
    !messageEl.classList.contains("startGroupCollapsed")
      ? messageVariable.textContent
      : null;

  // Retrieve closes actor id from the DOM.
  const actorEl =
    target.closest("[data-link-actor-id]") ||
    target.querySelector("[data-link-actor-id]");
  const actor = actorEl ? actorEl.dataset.linkActorId : null;

  const rootObjectInspector = target.closest(".object-inspector");
  const rootActor = rootObjectInspector
    ? rootObjectInspector.querySelector("[data-link-actor-id]")
    : null;
  // We can have object which are not displayed inside an ObjectInspector (e.g. Errors),
  // so let's default to `actor`.
  const rootActorId = rootActor ? rootActor.dataset.linkActorId : actor;

  const elementNode =
    target.closest(".objectBox-node") || target.closest(".objectBox-textNode");
  const isConnectedElement =
    elementNode && elementNode.querySelector(".open-inspector") !== null;

  const win = parentNode.ownerDocument.defaultView;
  const selection = win.getSelection();

  const { source, request, messageId } = message || {};

  const menu = new Menu({ id: "webconsole-menu" });

  // Copy URL for a network request.
  menu.append(
    new MenuItem({
      id: "console-menu-copy-url",
      label: l10n.getStr("webconsole.menu.copyURL.label"),
      accesskey: l10n.getStr("webconsole.menu.copyURL.accesskey"),
      visible: source === MESSAGE_SOURCE.NETWORK,
      click: () => {
        if (!request) {
          return;
        }
        clipboardHelper.copyString(request.url);
      },
    })
  );

  if (toolbox && request) {
    // Open Network message in the Network panel.
    menu.append(
      new MenuItem({
        id: "console-menu-open-in-network-panel",
        label: l10n.getStr("webconsole.menu.openInNetworkPanel.label"),
        accesskey: l10n.getStr("webconsole.menu.openInNetworkPanel.accesskey"),
        visible: source === MESSAGE_SOURCE.NETWORK,
        click: () => dispatch(actions.openNetworkPanel(message.messageId)),
      })
    );
    // Resend Network message.
    menu.append(
      new MenuItem({
        id: "console-menu-resend-network-request",
        label: l10n.getStr("webconsole.menu.resendNetworkRequest.label"),
        accesskey: l10n.getStr(
          "webconsole.menu.resendNetworkRequest.accesskey"
        ),
        visible: source === MESSAGE_SOURCE.NETWORK,
        click: () => dispatch(actions.resendNetworkRequest(messageId)),
      })
    );
  }

  // Open URL in a new tab for a network request.
  menu.append(
    new MenuItem({
      id: "console-menu-open-url",
      label: l10n.getStr("webconsole.menu.openURL.label"),
      accesskey: l10n.getStr("webconsole.menu.openURL.accesskey"),
      visible: source === MESSAGE_SOURCE.NETWORK,
      click: () => {
        if (!request) {
          return;
        }
        openContentLink(request.url);
      },
    })
  );

  // Open DOM node in the Inspector panel.
  const contentDomReferenceEl = target.closest(
    "[data-link-content-dom-reference]"
  );
  if (isConnectedElement && contentDomReferenceEl) {
    const contentDomReference = contentDomReferenceEl.getAttribute(
      "data-link-content-dom-reference"
    );

    menu.append(
      new MenuItem({
        id: "console-menu-open-node",
        label: l10n.getStr("webconsole.menu.openNodeInInspector.label"),
        accesskey: l10n.getStr("webconsole.menu.openNodeInInspector.accesskey"),
        disabled: false,
        click: () =>
          dispatch(
            actions.openNodeInInspector(JSON.parse(contentDomReference))
          ),
      })
    );
  }

  // Store as global variable.
  menu.append(
    new MenuItem({
      id: "console-menu-store",
      label: l10n.getStr("webconsole.menu.storeAsGlobalVar.label"),
      accesskey: l10n.getStr("webconsole.menu.storeAsGlobalVar.accesskey"),
      disabled: !actor,
      click: () => dispatch(actions.storeAsGlobal(actor)),
    })
  );

  // Copy message or grip.
  menu.append(
    new MenuItem({
      id: "console-menu-copy",
      label: l10n.getStr("webconsole.menu.copyMessage.label"),
      accesskey: l10n.getStr("webconsole.menu.copyMessage.accesskey"),
      // Disabled if there is no selection and no message element available to copy.
      disabled: selection.isCollapsed && !clipboardText,
      click: () => {
        if (selection.isCollapsed) {
          // If the selection is empty/collapsed, copy the text content of the
          // message for which the context menu was opened.
          clipboardHelper.copyString(clipboardText);
        } else {
          clipboardHelper.copyString(selection.toString());
        }
      },
    })
  );

  // Copy message object.
  menu.append(
    new MenuItem({
      id: "console-menu-copy-object",
      label: l10n.getStr("webconsole.menu.copyObject.label"),
      accesskey: l10n.getStr("webconsole.menu.copyObject.accesskey"),
      // Disabled if there is no actor and no variable text associated.
      disabled: !actor && !variableText,
      click: () => dispatch(actions.copyMessageObject(actor, variableText)),
    })
  );

  // Export to clipboard
  menu.append(
    new MenuItem({
      id: "console-menu-export-clipboard",
      label: l10n.getStr("webconsole.menu.copyAllMessages.label"),
      accesskey: l10n.getStr("webconsole.menu.copyAllMessages.accesskey"),
      disabled: false,
      async click() {
        const outputText =
          await getUnvirtualizedConsoleOutputText(webConsoleWrapper);
        clipboardHelper.copyString(outputText);
      },
    })
  );

  // Export to file
  menu.append(
    new MenuItem({
      id: "console-menu-export-file",
      label: l10n.getStr("webconsole.menu.saveAllMessagesFile.label"),
      accesskey: l10n.getStr("webconsole.menu.saveAllMessagesFile.accesskey"),
      disabled: false,
      // Note: not async, but returns a promise for the actual save.
      click: async () => {
        const date = new Date();
        const suggestedName =
          `console-export-${date.getFullYear()}-` +
          `${date.getMonth() + 1}-${date.getDate()}_${date.getHours()}-` +
          `${date.getMinutes()}-${date.getSeconds()}.txt`;
        const outputText =
          await getUnvirtualizedConsoleOutputText(webConsoleWrapper);
        const data = new TextEncoder().encode(outputText);
        saveAs(window, data, suggestedName);
      },
    })
  );

  // Open object in sidebar.
  const shouldOpenSidebar = store.getState().prefs.sidebarToggle;
  if (shouldOpenSidebar) {
    menu.append(
      new MenuItem({
        id: "console-menu-open-sidebar",
        label: l10n.getStr("webconsole.menu.openInSidebar.label1"),
        accesskey: l10n.getStr("webconsole.menu.openInSidebar.accesskey"),
        disabled: !rootActorId,
        click: () => dispatch(actions.openSidebar(messageId, rootActorId)),
      })
    );
  }

  if (url) {
    menu.append(
      new MenuItem({
        id: "console-menu-open-url",
        label: l10n.getStr("webconsole.menu.openURL.label"),
        accesskey: l10n.getStr("webconsole.menu.openURL.accesskey"),
        click: () =>
          openContentLink(url, {
            inBackground: true,
            relatedToCurrent: true,
          }),
      })
    );
    menu.append(
      new MenuItem({
        id: "console-menu-copy-url",
        label: l10n.getStr("webconsole.menu.copyURL.label"),
        accesskey: l10n.getStr("webconsole.menu.copyURL.accesskey"),
        click: () => clipboardHelper.copyString(url),
      })
    );
  }

  // Emit the "menu-open" event for testing.
  const { screenX, screenY } = event;
  menu.once("open", () => webConsoleWrapper.emitForTests("menu-open"));
  menu.popup(screenX, screenY, hud.chromeWindow.document);

  return menu;
}

exports.createContextMenu = createContextMenu;

/**
 * Returns the whole text content of the console output.
 * We're creating a new ConsoleOutput using the current store, turning off virtualization
 * so we can have access to all the messages.
 *
 * @param {WebConsoleWrapper} webConsoleWrapper
 * @returns Promise<String>
 */

async function getUnvirtualizedConsoleOutputText(webConsoleWrapper) {
  return new Promise(resolve => {
    const ReactDOM = require("resource://devtools/client/shared/vendor/react-dom.js");
    const {
      createElement,
      createFactory,
    } = require("resource://devtools/client/shared/vendor/react.js");
    const ConsoleOutput = createFactory(
      require("resource://devtools/client/webconsole/components/Output/ConsoleOutput.js")
    );
    const {
      Provider,
      createProvider,
    } = require("resource://devtools/client/shared/vendor/react-redux.js");

    const { parentNode, toolbox } = webConsoleWrapper;
    const doc = parentNode.ownerDocument;

    // Create an element that won't impact the layout of the console
    const singleUseElement = doc.createElement("section");
    singleUseElement.classList.add("clipboard-only");
    doc.body.append(singleUseElement);

    const consoleOutput = ConsoleOutput({
      serviceContainer: {
        ...webConsoleWrapper.getServiceContainer(),
        preventStacktraceInitialRenderDelay: true,
      },
      disableVirtualization: true,
    });

    ReactDOM.render(
      createElement(
        Provider,
        {
          store: webConsoleWrapper.getStore(),
        },
        toolbox
          ? createElement(
              createProvider(toolbox.commands.targetCommand.storeId),
              { store: toolbox.commands.targetCommand.store },
              consoleOutput
            )
          : consoleOutput
      ),
      singleUseElement,
      () => {
        resolve(getElementText(singleUseElement));
        singleUseElement.remove();
        ReactDOM.unmountComponentAtNode(singleUseElement);
      }
    );
  });
}

98%


¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge