diff --git a/browser/actors/PromptParent.sys.mjs b/browser/actors/PromptParent.sys.mjs index 2e1b3e162a75..f98edc5b5cd3 100644 --- a/browser/actors/PromptParent.sys.mjs +++ b/browser/actors/PromptParent.sys.mjs @@ -301,6 +301,7 @@ export class PromptParent extends JSWindowActorParent { args.promptAborted = false; args.openedWithTabDialog = true; + args.owningBrowsingContext = this.browsingContext; // Convert args object to a prop bag for the dialog to consume. let bag; diff --git a/browser/components/contentanalysis/content/ContentAnalysis.sys.mjs b/browser/components/contentanalysis/content/ContentAnalysis.sys.mjs index 6c4e8de2e6d0..c8a8545cf1c1 100644 --- a/browser/components/contentanalysis/content/ContentAnalysis.sys.mjs +++ b/browser/components/contentanalysis/content/ContentAnalysis.sys.mjs @@ -221,7 +221,7 @@ export const ContentAnalysis = { } case "dlp-request-made": { - const request = aSubj; + const request = aSubj.QueryInterface(Ci.nsIContentAnalysisRequest); if (!request) { console.error( "Showing in-browser Content Analysis notification but no request was passed" @@ -272,7 +272,7 @@ export const ContentAnalysis = { } break; case "dlp-response": - const request = aSubj; + const request = aSubj.QueryInterface(Ci.nsIContentAnalysisResponse); // Cancels timer or slow message UI, // if present, and possibly presents the CA verdict. if (!request) { diff --git a/toolkit/components/prompts/content/commonDialog.js b/toolkit/components/prompts/content/commonDialog.js index 11b3e820177f..5a9d43ee636a 100644 --- a/toolkit/components/prompts/content/commonDialog.js +++ b/toolkit/components/prompts/content/commonDialog.js @@ -5,6 +5,18 @@ const { CommonDialog } = ChromeUtils.importESModule( "resource://gre/modules/CommonDialog.sys.mjs" ); +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +const lazy = {}; + +XPCOMUtils.defineLazyServiceGetter( + lazy, + "gContentAnalysis", + "@mozilla.org/contentanalysis;1", + Ci.nsIContentAnalysis +); // imported by adjustableTitle.js loaded in the same context: /* globals PromptUtils */ @@ -123,6 +135,58 @@ function commonDialogOnLoad() { // If the icon hasn't loaded yet, size the window to the content again when // it does, as its layout can change. ui.infoIcon.addEventListener("load", () => window.sizeToContent()); + if (lazy.gContentAnalysis.isActive && args.owningBrowsingContext?.isContent) { + ui.loginTextbox?.addEventListener("paste", async event => { + let data = event.clipboardData.getData("text/plain"); + if (data?.length > 0) { + // Prevent the paste from happening until content analysis returns a response + event.preventDefault(); + // Selections can be forward or backward, so use min/max + const startIndex = Math.min( + ui.loginTextbox.selectionStart, + ui.loginTextbox.selectionEnd + ); + const endIndex = Math.max( + ui.loginTextbox.selectionStart, + ui.loginTextbox.selectionEnd + ); + const selectionDirection = + endIndex < startIndex ? "backward" : "forward"; + try { + const response = await lazy.gContentAnalysis.analyzeContentRequest( + { + requestToken: Services.uuid.generateUUID().toString(), + resources: [], + analysisType: Ci.nsIContentAnalysis.eBulkDataEntry, + operationTypeForDisplay: Ci.nsIContentAnalysisRequest.eClipboard, + url: args.owningBrowsingContext.currentURI.spec, + textContent: data, + windowGlobalParent: + args.owningBrowsingContext.currentWindowContext, + }, + true + ); + if (response.shouldAllowContent) { + ui.loginTextbox.value = + ui.loginTextbox.value.slice(0, startIndex) + + data + + ui.loginTextbox.value.slice(endIndex); + ui.loginTextbox.focus(); + if (startIndex !== endIndex) { + // Select the pasted text + ui.loginTextbox.setSelectionRange( + startIndex, + startIndex + data.length, + selectionDirection + ); + } + } + } catch (error) { + console.error("Content analysis request returned error: ", error); + } + } + }); + } window.getAttention(); }