Bug 1972786 - show various DLP agent errors for download operations a=diannaS

Show these errors in the download panel, etc.

Original Revision: https://phabricator.services.mozilla.com/D254295

Differential Revision: https://phabricator.services.mozilla.com/D258587
This commit is contained in:
Greg Stoll
2025-07-24 20:18:34 +00:00
committed by dsmith@mozilla.com
parent 5adc9375da
commit b48f6f4035
7 changed files with 71 additions and 8 deletions

View File

@@ -352,8 +352,8 @@ export const ContentAnalysis = {
windowAndResourceNameOrOperationType.resourceNameOrOperationType
?.operationType === Ci.nsIContentAnalysisRequest.eDownload
) {
// Don't show warn/block dialogs for downloads; they're shown inside
// the downloads panel.
// Don't show warn/block/error dialogs for downloads; they're shown
// inside the downloads panel.
return;
}
const responseResult =
@@ -744,10 +744,7 @@ export const ContentAnalysis = {
_getErrorDialogMessage(aResourceNameOrOperationType) {
if (aResourceNameOrOperationType.name) {
return this.l10n.formatValueSync(
aResourceNameOrOperationType.operationType ==
Ci.nsIContentAnalysisRequest.eUpload
? "contentanalysis-error-message-upload-file"
: "contentanalysis-error-message-download-file",
"contentanalysis-error-message-upload-file",
{ filename: aResourceNameOrOperationType.name }
);
}

View File

@@ -75,6 +75,10 @@ const kDownloadsFluentStrings = new Localization(
);
const kDownloadsStringsRequiringFormatting = {
contentAnalysisNoAgentError: true,
contentAnalysisInvalidAgentSignatureError: true,
contentAnalysisUnspecifiedError: true,
contentAnalysisTimeoutError: true,
sizeWithUnits: true,
statusSeparator: true,
statusSeparatorBeforeNumber: true,

View File

@@ -34,6 +34,13 @@ XPCOMUtils.defineLazyServiceGetter(
Ci.nsIApplicationReputationService
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"contentAnalysisAgentName",
"browser.contentanalysis.agent_name",
"A DLP agent"
);
import { Integration } from "resource://gre/modules/Integration.sys.mjs";
Integration.downloads.defineESModuleGetter(
@@ -877,6 +884,31 @@ DownloadsViewUI.DownloadElementShell.prototype = {
}
},
getContentAnalysisErrorTitle(strings, cancelError) {
switch (cancelError) {
case Ci.nsIContentAnalysisResponse.eNoAgent:
return strings.contentAnalysisNoAgentError(
lazy.contentAnalysisAgentName
);
case Ci.nsIContentAnalysisResponse.eInvalidAgentSignature:
return strings.contentAnalysisInvalidAgentSignatureError(
lazy.contentAnalysisAgentName
);
case Ci.nsIContentAnalysisResponse.eTimeout:
return strings.contentAnalysisTimeoutError(
lazy.contentAnalysisAgentName
);
case Ci.nsIContentAnalysisResponse.eErrorOther:
return strings.contentAnalysisUnspecifiedError(
lazy.contentAnalysisAgentName
);
default:
// This also handles the case when cancelError is undefined
// because the request wasn't cancelled at all.
return strings.blockedByContentAnalysis;
}
},
/**
* Returns [title, [details1, details2]] for blocked downloads.
* The title or details could be raw strings or l10n objects.
@@ -926,7 +958,10 @@ DownloadsViewUI.DownloadElementShell.prototype = {
break;
}
return [
s.blockedByContentAnalysis,
this.getContentAnalysisErrorTitle(
s,
this.download.error.contentAnalysisCancelError
),
[s.unblockContentAnalysis1, s.unblockContentAnalysis2],
];
case lazy.Downloads.Error.BLOCK_VERDICT_DOWNLOAD_SPAM: {

View File

@@ -35,6 +35,13 @@ blockedPotentiallyUnwanted=This file may harm your computer.
blockedPotentiallyInsecure=File not downloaded: Potential security risk.
blockedUncommon2=This file is not commonly downloaded.
blockedByContentAnalysis=This file was blocked by your organization.
# LOCALIZATION NOTE (contentAnalysisNoAgentError, contentAnalysisInvalidAgentSignatureError,
# contentAnalysisUnspecifiedError, contentAnalysisTimeoutError):
# %1$S is replaced with the name of the DLP agent.
contentAnalysisNoAgentError=File was blocked because %1$S is not reachable.
contentAnalysisInvalidAgentSignatureError=File was blocked because %1$S failed signature verification.
contentAnalysisUnspecifiedError=File was blocked because of an error in communicating with %1$S.
contentAnalysisTimeoutError=%1$S timed out, so this file was blocked.
warnedByContentAnalysis=This download may be unsafe and requires confirmation.
# LOCALIZATION NOTE (fileMovedOrMissing):

View File

@@ -1936,6 +1936,7 @@ export var DownloadError = function (aProperties) {
} else if (aProperties.becauseBlockedByContentAnalysis) {
this.becauseBlocked = true;
this.becauseBlockedByContentAnalysis = true;
this.contentAnalysisCancelError = aProperties.contentAnalysisCancelError;
this.contentAnalysisWarnRequestToken =
aProperties.contentAnalysisWarnRequestToken;
this.reputationCheckVerdict = aProperties.reputationCheckVerdict;
@@ -2001,6 +2002,12 @@ DownloadError.prototype = {
*/
becauseBlockedByContentAnalysis: false,
/**
* The cancelError returned by the content analysis tool, which corresponds
* to the nsIContentAnalysisResponse.CancelError enum. May be undefined.
*/
contentAnalysisCancelError: undefined,
/**
* If becauseBlockedByReputationCheck is true, indicates the detailed reason
* why the download was blocked, according to the "BLOCK_VERDICT_" constants.
@@ -2063,7 +2070,8 @@ DownloadError.fromSerializable = function (aSerializable) {
property != "becauseBlockedByParentalControls" &&
property != "becauseBlockedByReputationCheck" &&
property != "becauseBlockedByContentAnalysis" &&
property != "reputationCheckVerdict"
property != "reputationCheckVerdict" &&
property != "contentAnalysisCancelError"
);
return e;
@@ -2760,6 +2768,8 @@ DownloadCopySaver.prototype = {
throw new DownloadError({
becauseBlockedByContentAnalysis: true,
reputationCheckVerdict: downloadErrorVerdict,
contentAnalysisCancelError:
permissionResult.contentAnalysisCancelError,
contentAnalysisWarnRequestToken:
permissionResult.contentAnalysisWarnRequestToken,
});

View File

@@ -151,6 +151,10 @@ export let DownloadHistory = {
if (download.error && download.error.reputationCheckVerdict) {
metaData.reputationCheckVerdict = download.error.reputationCheckVerdict;
}
if (download?.error?.hasOwnProperty("contentAnalysisCancelError")) {
metaData.contentAnalysisCancelError =
download.error.contentAnalysisCancelError;
}
// This should be executed before any async parts, to ensure the cache is
// updated before any notifications are activated.
@@ -444,6 +448,7 @@ class HistoryDownload {
} else if (metaData.state == METADATA_STATE_BLOCKED_CONTENT_ANALYSIS) {
this.error = {
becauseBlockedByContentAnalysis: true,
contentAnalysisCancelError: metaData.contentAnalysisCancelError,
reputationCheckVerdict: metaData.reputationCheckVerdict || "",
};
} else if (metaData.state == METADATA_STATE_DIRTY) {

View File

@@ -552,11 +552,16 @@ export var DownloadIntegration = {
/* autoAcknowledge*/ true
)
.then(response => {
let cancelError;
if (response?.action === Ci.nsIContentAnalysisResponse.eCanceled) {
cancelError = response.cancelError;
}
return {
verdict: response.shouldAllowContent
? Ci.nsIApplicationReputationService.VERDICT_SAFE
: Ci.nsIApplicationReputationService.VERDICT_DANGEROUS,
shouldBlock: !response.shouldAllowContent,
contentAnalysisCancelError: cancelError,
contentAnalysisWarnRequestToken: undefined,
};
});