mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-03 01:38:46 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			5.5 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/. */
 | 
						|
 | 
						|
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
 | 
						|
 | 
						|
const lazy = {};
 | 
						|
 | 
						|
ChromeUtils.defineESModuleGetters(lazy, {
 | 
						|
  BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
 | 
						|
  E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
 | 
						|
});
 | 
						|
 | 
						|
export class MiddleMousePasteHandlerChild extends JSWindowActorChild {
 | 
						|
  handleEvent(clickEvent) {
 | 
						|
    if (
 | 
						|
      clickEvent.defaultPrevented ||
 | 
						|
      clickEvent.button != 1 ||
 | 
						|
      MiddleMousePasteHandlerChild.autoscrollEnabled
 | 
						|
    ) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    this.manager
 | 
						|
      .getActor("ClickHandler")
 | 
						|
      .handleClickEvent(
 | 
						|
        clickEvent,
 | 
						|
        /* is from middle mouse paste handler */ true
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  onProcessedClick(data) {
 | 
						|
    this.sendAsyncMessage("MiddleClickPaste", data);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
XPCOMUtils.defineLazyPreferenceGetter(
 | 
						|
  MiddleMousePasteHandlerChild,
 | 
						|
  "autoscrollEnabled",
 | 
						|
  "general.autoScroll",
 | 
						|
  true
 | 
						|
);
 | 
						|
 | 
						|
export class ClickHandlerChild extends JSWindowActorChild {
 | 
						|
  handleEvent(wrapperEvent) {
 | 
						|
    this.handleClickEvent(wrapperEvent.sourceEvent);
 | 
						|
  }
 | 
						|
 | 
						|
  handleClickEvent(event, isFromMiddleMousePasteHandler = false) {
 | 
						|
    if (event.defaultPrevented || event.button == 2) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    // Don't do anything on editable things, we shouldn't open links in
 | 
						|
    // contenteditables, and editor needs to possibly handle middlemouse paste
 | 
						|
    let composedTarget = event.composedTarget;
 | 
						|
    if (
 | 
						|
      composedTarget.isContentEditable ||
 | 
						|
      (composedTarget.ownerDocument &&
 | 
						|
        composedTarget.ownerDocument.designMode == "on") ||
 | 
						|
      ChromeUtils.getClassName(composedTarget) == "HTMLInputElement" ||
 | 
						|
      ChromeUtils.getClassName(composedTarget) == "HTMLTextAreaElement"
 | 
						|
    ) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    let originalTarget = event.originalTarget;
 | 
						|
    let ownerDoc = originalTarget.ownerDocument;
 | 
						|
    if (!ownerDoc) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // Handle click events from about pages
 | 
						|
    if (event.button == 0) {
 | 
						|
      if (ownerDoc.documentURI.startsWith("about:blocked")) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // For untrusted events, require a valid transient user gesture activation.
 | 
						|
    if (!event.isTrusted && !ownerDoc.hasValidTransientUserGestureActivation) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    let [href, node, principal] =
 | 
						|
      lazy.BrowserUtils.hrefAndLinkNodeForClickEvent(event);
 | 
						|
 | 
						|
    let csp = ownerDoc.csp;
 | 
						|
    if (csp) {
 | 
						|
      csp = lazy.E10SUtils.serializeCSP(csp);
 | 
						|
    }
 | 
						|
 | 
						|
    let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
 | 
						|
      Ci.nsIReferrerInfo
 | 
						|
    );
 | 
						|
    if (node) {
 | 
						|
      referrerInfo.initWithElement(node);
 | 
						|
    } else {
 | 
						|
      referrerInfo.initWithDocument(ownerDoc);
 | 
						|
    }
 | 
						|
    referrerInfo = lazy.E10SUtils.serializeReferrerInfo(referrerInfo);
 | 
						|
 | 
						|
    let json = {
 | 
						|
      button: event.button,
 | 
						|
      shiftKey: event.shiftKey,
 | 
						|
      ctrlKey: event.ctrlKey,
 | 
						|
      metaKey: event.metaKey,
 | 
						|
      altKey: event.altKey,
 | 
						|
      href: null,
 | 
						|
      title: null,
 | 
						|
      csp,
 | 
						|
      referrerInfo,
 | 
						|
    };
 | 
						|
 | 
						|
    if (href && !isFromMiddleMousePasteHandler) {
 | 
						|
      try {
 | 
						|
        Services.scriptSecurityManager.checkLoadURIStrWithPrincipal(
 | 
						|
          principal,
 | 
						|
          href
 | 
						|
        );
 | 
						|
      } catch (e) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      if (
 | 
						|
        !event.isTrusted &&
 | 
						|
        lazy.BrowserUtils.whereToOpenLink(event) != "current"
 | 
						|
      ) {
 | 
						|
        // If we'll open the link, we want to consume the user gesture
 | 
						|
        // activation to ensure that we don't allow multiple links to open
 | 
						|
        // from one user gesture.
 | 
						|
        // Avoid doing so for links opened in the current tab, which get
 | 
						|
        // handled later, by gecko, as otherwise its popup blocker will stop
 | 
						|
        // the link from opening.
 | 
						|
        // We will do the same check (whereToOpenLink) again in the parent and
 | 
						|
        // avoid handling the click for such links... but we still need the
 | 
						|
        // click information in the parent because otherwise places link
 | 
						|
        // tracking breaks. (bug 1742894 tracks improving this.)
 | 
						|
        ownerDoc.consumeTransientUserGestureActivation();
 | 
						|
        // We don't care about the return value because we already checked that
 | 
						|
        // hasValidTransientUserGestureActivation was true earlier in this
 | 
						|
        // function.
 | 
						|
      }
 | 
						|
 | 
						|
      json.href = href;
 | 
						|
      if (node) {
 | 
						|
        json.title = node.getAttribute("title");
 | 
						|
      }
 | 
						|
 | 
						|
      if (
 | 
						|
        (ownerDoc.URL === "about:newtab" || ownerDoc.URL === "about:home") &&
 | 
						|
        node.dataset.isSponsoredLink === "true"
 | 
						|
      ) {
 | 
						|
        json.globalHistoryOptions = { triggeringSponsoredURL: href };
 | 
						|
      }
 | 
						|
 | 
						|
      // If a link element is clicked with middle button, user wants to open
 | 
						|
      // the link somewhere rather than pasting clipboard content.  Therefore,
 | 
						|
      // when it's clicked with middle button, we should prevent multiple
 | 
						|
      // actions here to avoid leaking clipboard content unexpectedly.
 | 
						|
      // Note that whether the link will work actually or not does not matter
 | 
						|
      // because in this case, user does not intent to paste clipboard content.
 | 
						|
      // We also need to do this to prevent multiple tabs opening if there are
 | 
						|
      // nested link elements.
 | 
						|
      event.preventMultipleActions();
 | 
						|
 | 
						|
      this.sendAsyncMessage("Content:Click", json);
 | 
						|
    }
 | 
						|
 | 
						|
    // This might be middle mouse navigation, in which case pass this back:
 | 
						|
    if (!href && event.button == 1 && isFromMiddleMousePasteHandler) {
 | 
						|
      this.manager.getActor("MiddleMousePasteHandler").onProcessedClick(json);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |