1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
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/. */
6 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
10 ChromeUtils.defineESModuleGetters(lazy, {
11 BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
12 E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
15 export class MiddleMousePasteHandlerChild extends JSWindowActorChild {
16 handleEvent(clickEvent) {
18 clickEvent.defaultPrevented ||
19 clickEvent.button != 1 ||
20 MiddleMousePasteHandlerChild.autoscrollEnabled
25 .getActor("ClickHandler")
28 /* is from middle mouse paste handler */ true
32 onProcessedClick(data) {
33 this.sendAsyncMessage("MiddleClickPaste", data);
37 XPCOMUtils.defineLazyPreferenceGetter(
38 MiddleMousePasteHandlerChild,
44 export class ClickHandlerChild extends JSWindowActorChild {
45 handleEvent(wrapperEvent) {
46 this.handleClickEvent(wrapperEvent.sourceEvent);
49 handleClickEvent(event, isFromMiddleMousePasteHandler = false) {
50 if (event.defaultPrevented || event.button == 2) {
53 // Don't do anything on editable things, we shouldn't open links in
54 // contenteditables, and editor needs to possibly handle middlemouse paste
55 let composedTarget = event.composedTarget;
57 composedTarget.isContentEditable ||
58 (composedTarget.ownerDocument &&
59 composedTarget.ownerDocument.designMode == "on") ||
60 ChromeUtils.getClassName(composedTarget) == "HTMLInputElement" ||
61 ChromeUtils.getClassName(composedTarget) == "HTMLTextAreaElement"
66 let originalTarget = event.originalTarget;
67 let ownerDoc = originalTarget.ownerDocument;
72 // Handle click events from about pages
73 if (event.button == 0) {
74 if (ownerDoc.documentURI.startsWith("about:blocked")) {
79 // For untrusted events, require a valid transient user gesture activation.
80 if (!event.isTrusted && !ownerDoc.hasValidTransientUserGestureActivation) {
84 let [href, node, principal] =
85 lazy.BrowserUtils.hrefAndLinkNodeForClickEvent(event);
87 let csp = ownerDoc.csp;
89 csp = lazy.E10SUtils.serializeCSP(csp);
92 let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
96 referrerInfo.initWithElement(node);
98 referrerInfo.initWithDocument(ownerDoc);
100 referrerInfo = lazy.E10SUtils.serializeReferrerInfo(referrerInfo);
103 button: event.button,
104 shiftKey: event.shiftKey,
105 ctrlKey: event.ctrlKey,
106 metaKey: event.metaKey,
107 altKey: event.altKey,
114 if (href && !isFromMiddleMousePasteHandler) {
116 Services.scriptSecurityManager.checkLoadURIStrWithPrincipal(
126 lazy.BrowserUtils.whereToOpenLink(event) != "current"
128 // If we'll open the link, we want to consume the user gesture
129 // activation to ensure that we don't allow multiple links to open
130 // from one user gesture.
131 // Avoid doing so for links opened in the current tab, which get
132 // handled later, by gecko, as otherwise its popup blocker will stop
133 // the link from opening.
134 // We will do the same check (whereToOpenLink) again in the parent and
135 // avoid handling the click for such links... but we still need the
136 // click information in the parent because otherwise places link
137 // tracking breaks. (bug 1742894 tracks improving this.)
138 ownerDoc.consumeTransientUserGestureActivation();
139 // We don't care about the return value because we already checked that
140 // hasValidTransientUserGestureActivation was true earlier in this
146 json.title = node.getAttribute("title");
150 (ownerDoc.URL === "about:newtab" || ownerDoc.URL === "about:home") &&
151 node.dataset.isSponsoredLink === "true"
153 json.globalHistoryOptions = { triggeringSponsoredURL: href };
156 // If a link element is clicked with middle button, user wants to open
157 // the link somewhere rather than pasting clipboard content. Therefore,
158 // when it's clicked with middle button, we should prevent multiple
159 // actions here to avoid leaking clipboard content unexpectedly.
160 // Note that whether the link will work actually or not does not matter
161 // because in this case, user does not intent to paste clipboard content.
162 // We also need to do this to prevent multiple tabs opening if there are
163 // nested link elements.
164 event.preventMultipleActions();
166 this.sendAsyncMessage("Content:Click", json);
169 // This might be middle mouse navigation, in which case pass this back:
170 if (!href && event.button == 1 && isFromMiddleMousePasteHandler) {
171 this.manager.getActor("MiddleMousePasteHandler").onProcessedClick(json);