mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Bug 1254100 - Part 2 - Downloads blocked by Application Reputation should provide information about the verdict. r=mak
MozReview-Commit-ID: FYH5Tdtbzn --HG-- extra : rebase_source : a59e79ac247d5f6d039d25f6ee6aea6cf2b5dbe6
This commit is contained in:
parent
9badfa332e
commit
44ddde4b6e
@ -140,13 +140,6 @@ PrefObserver.register({
|
||||
* and provides shared methods for all the instances of the user interface.
|
||||
*/
|
||||
this.DownloadsCommon = {
|
||||
/**
|
||||
* Constants with the different types of unblock messages.
|
||||
*/
|
||||
BLOCK_VERDICT_MALWARE: "Malware",
|
||||
BLOCK_VERDICT_POTENTIALLY_UNWANTED: "PotentiallyUnwanted",
|
||||
BLOCK_VERDICT_UNCOMMON: "Uncommon",
|
||||
|
||||
/**
|
||||
* Returns an object whose keys are the string names from the downloads string
|
||||
* bundle, and whose values are either the translated strings or functions
|
||||
@ -528,15 +521,17 @@ this.DownloadsCommon = {
|
||||
* Displays an alert message box which asks the user if they want to
|
||||
* unblock the downloaded file or not.
|
||||
*
|
||||
* @param aType
|
||||
* The type of malware the downloaded file contains.
|
||||
* @param aVerdict
|
||||
* The detailed reason why the download was blocked, according to the
|
||||
* "Downloads.Error.BLOCK_VERDICT_" constants. If an unknown reason is
|
||||
* specified, "Downloads.Error.BLOCK_VERDICT_MALWARE" is assumed.
|
||||
* @param aOwnerWindow
|
||||
* The window with which this action is associated.
|
||||
*
|
||||
* @return True to unblock the file, false to keep the user safe and
|
||||
* cancel the operation.
|
||||
*/
|
||||
confirmUnblockDownload: Task.async(function* (aType, aOwnerWindow) {
|
||||
confirmUnblockDownload: Task.async(function* (aVerdict, aOwnerWindow) {
|
||||
let s = DownloadsCommon.strings;
|
||||
let title = s.unblockHeader;
|
||||
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
|
||||
@ -547,15 +542,15 @@ this.DownloadsCommon = {
|
||||
let okButton = s.unblockButtonContinue;
|
||||
let cancelButton = s.unblockButtonCancel;
|
||||
|
||||
switch (aType) {
|
||||
case this.BLOCK_VERDICT_MALWARE:
|
||||
type = s.unblockTypeMalware;
|
||||
switch (aVerdict) {
|
||||
case Downloads.Error.BLOCK_VERDICT_UNCOMMON:
|
||||
type = s.unblockTypeUncommon;
|
||||
break;
|
||||
case this.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
|
||||
case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
|
||||
type = s.unblockTypePotentiallyUnwanted;
|
||||
break;
|
||||
case this.BLOCK_VERDICT_UNCOMMON:
|
||||
type = s.unblockTypeUncommon;
|
||||
default: // Assume Downloads.Error.BLOCK_VERDICT_MALWARE
|
||||
type = s.unblockTypeMalware;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -372,8 +372,8 @@ HistoryDownloadElementShell.prototype = {
|
||||
},
|
||||
|
||||
downloadsCmd_unblock() {
|
||||
DownloadsCommon.confirmUnblockDownload(DownloadsCommon.BLOCK_VERDICT_MALWARE,
|
||||
window).then((confirmed) => {
|
||||
let verdict = this.download.error.reputationCheckVerdict;
|
||||
DownloadsCommon.confirmUnblockDownload(verdict, window).then(confirmed => {
|
||||
if (confirmed) {
|
||||
return this.download.unblock();
|
||||
}
|
||||
|
@ -1099,8 +1099,8 @@ DownloadsViewItem.prototype = {
|
||||
|
||||
downloadsCmd_unblock() {
|
||||
DownloadsPanel.hidePanel();
|
||||
DownloadsCommon.confirmUnblockDownload(DownloadsCommon.BLOCK_VERDICT_MALWARE,
|
||||
window).then((confirmed) => {
|
||||
let verdict = this.download.error.reputationCheckVerdict;
|
||||
DownloadsCommon.confirmUnblockDownload(verdict, window).then(confirmed => {
|
||||
if (confirmed) {
|
||||
return this.download.unblock();
|
||||
}
|
||||
|
@ -33,14 +33,14 @@ function addDialogOpenObserver(buttonAction) {
|
||||
|
||||
add_task(function* test_confirm_unblock_dialog_unblock() {
|
||||
addDialogOpenObserver("accept");
|
||||
let result = yield DownloadsCommon.confirmUnblockDownload(DownloadsCommon.BLOCK_VERDICT_MALWARE,
|
||||
let result = yield DownloadsCommon.confirmUnblockDownload(Downloads.Error.BLOCK_VERDICT_MALWARE,
|
||||
window);
|
||||
ok(result, "Should return true when the user clicks on `Unblock` button.");
|
||||
});
|
||||
|
||||
add_task(function* test_confirm_unblock_dialog_keep_safe() {
|
||||
addDialogOpenObserver("cancel");
|
||||
let result = yield DownloadsCommon.confirmUnblockDownload(DownloadsCommon.BLOCK_VERDICT_MALWARE,
|
||||
let result = yield DownloadsCommon.confirmUnblockDownload(Downloads.Error.BLOCK_VERDICT_MALWARE,
|
||||
window);
|
||||
ok(!result, "Should return false when the user clicks on `Keep me safe` button.");
|
||||
});
|
||||
|
@ -1529,6 +1529,7 @@ this.DownloadError = function (aProperties)
|
||||
} else if (aProperties.becauseBlockedByReputationCheck) {
|
||||
this.becauseBlocked = true;
|
||||
this.becauseBlockedByReputationCheck = true;
|
||||
this.reputationCheckVerdict = aProperties.reputationCheckVerdict || "";
|
||||
} else if (aProperties.becauseBlockedByRuntimePermissions) {
|
||||
this.becauseBlocked = true;
|
||||
this.becauseBlockedByRuntimePermissions = true;
|
||||
@ -1543,6 +1544,16 @@ this.DownloadError = function (aProperties)
|
||||
this.stack = new Error().stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* These constants are used by the reputationCheckVerdict property and indicate
|
||||
* the detailed reason why a download is blocked.
|
||||
*
|
||||
* @note These values should not be changed because they can be serialized.
|
||||
*/
|
||||
this.DownloadError.BLOCK_VERDICT_MALWARE = "Malware";
|
||||
this.DownloadError.BLOCK_VERDICT_POTENTIALLY_UNWANTED = "PotentiallyUnwanted";
|
||||
this.DownloadError.BLOCK_VERDICT_UNCOMMON = "Uncommon";
|
||||
|
||||
this.DownloadError.prototype = {
|
||||
__proto__: Error.prototype,
|
||||
|
||||
@ -1588,6 +1599,15 @@ this.DownloadError.prototype = {
|
||||
*/
|
||||
becauseBlockedByRuntimePermissions: false,
|
||||
|
||||
/**
|
||||
* If becauseBlockedByReputationCheck is true, indicates the detailed reason
|
||||
* why the download was blocked, according to the "BLOCK_VERDICT_" constants.
|
||||
*
|
||||
* If the download was not blocked or the reason for the block is unknown,
|
||||
* this will be an empty string.
|
||||
*/
|
||||
reputationCheckVerdict: "",
|
||||
|
||||
/**
|
||||
* If this DownloadError was caused by an exception this property will
|
||||
* contain the original exception. This will not be serialized when saving
|
||||
@ -1611,6 +1631,7 @@ this.DownloadError.prototype = {
|
||||
becauseBlockedByParentalControls: this.becauseBlockedByParentalControls,
|
||||
becauseBlockedByReputationCheck: this.becauseBlockedByReputationCheck,
|
||||
becauseBlockedByRuntimePermissions: this.becauseBlockedByRuntimePermissions,
|
||||
reputationCheckVerdict: this.reputationCheckVerdict,
|
||||
};
|
||||
|
||||
serializeUnknownProperties(this, serializable);
|
||||
@ -1636,7 +1657,8 @@ this.DownloadError.fromSerializable = function (aSerializable) {
|
||||
property != "becauseBlocked" &&
|
||||
property != "becauseBlockedByParentalControls" &&
|
||||
property != "becauseBlockedByReputationCheck" &&
|
||||
property != "becauseBlockedByRuntimePermissions");
|
||||
property != "becauseBlockedByRuntimePermissions" &&
|
||||
property != "reputationCheckVerdict");
|
||||
|
||||
return e;
|
||||
};
|
||||
@ -2148,7 +2170,9 @@ this.DownloadCopySaver.prototype = {
|
||||
let targetPath = this.download.target.path;
|
||||
let partFilePath = this.download.target.partFilePath;
|
||||
|
||||
if (yield DownloadIntegration.shouldBlockForReputationCheck(download)) {
|
||||
let { shouldBlock, verdict } =
|
||||
yield DownloadIntegration.shouldBlockForReputationCheck(download);
|
||||
if (shouldBlock) {
|
||||
download.progress = 100;
|
||||
download.hasPartialData = false;
|
||||
|
||||
@ -2166,7 +2190,10 @@ this.DownloadCopySaver.prototype = {
|
||||
download.hasBlockedData = true;
|
||||
}
|
||||
|
||||
throw new DownloadError({ becauseBlockedByReputationCheck: true });
|
||||
throw new DownloadError({
|
||||
becauseBlockedByReputationCheck: true,
|
||||
reputationCheckVerdict: verdict,
|
||||
});
|
||||
}
|
||||
|
||||
if (partFilePath) {
|
||||
|
@ -125,6 +125,20 @@ const kObserverTopics = [
|
||||
"xpcom-will-shutdown",
|
||||
];
|
||||
|
||||
/**
|
||||
* Maps nsIApplicationReputationService verdicts with the DownloadError ones.
|
||||
*/
|
||||
const kVerdictMap = {
|
||||
[Ci.nsIApplicationReputationService.VERDICT_DANGEROUS]:
|
||||
Downloads.Error.BLOCK_VERDICT_MALWARE,
|
||||
[Ci.nsIApplicationReputationService.VERDICT_UNCOMMON]:
|
||||
Downloads.Error.BLOCK_VERDICT_UNCOMMON,
|
||||
[Ci.nsIApplicationReputationService.VERDICT_POTENTIALLY_UNWANTED]:
|
||||
Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED,
|
||||
[Ci.nsIApplicationReputationService.VERDICT_DANGEROUS_HOST]:
|
||||
Downloads.Error.BLOCK_VERDICT_MALWARE,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadIntegration
|
||||
|
||||
@ -148,6 +162,7 @@ this.DownloadIntegration = {
|
||||
dontCheckApplicationReputation: true,
|
||||
#endif
|
||||
shouldBlockInTestForApplicationReputation: false,
|
||||
verdictInTestForApplicationReputation: "",
|
||||
shouldKeepBlockedDataInTest: false,
|
||||
dontOpenFileAndFolder: false,
|
||||
downloadDoneCalled: false,
|
||||
@ -531,11 +546,20 @@ this.DownloadIntegration = {
|
||||
* The download object.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves The boolean indicates to block downloads or not.
|
||||
* @resolves Object with the following properties:
|
||||
* {
|
||||
* shouldBlock: Whether the download should be blocked.
|
||||
* verdict: Detailed reason for the block, according to the
|
||||
* "Downloads.Error.BLOCK_VERDICT_" constants, or empty
|
||||
* string if the reason is unknown.
|
||||
* }
|
||||
*/
|
||||
shouldBlockForReputationCheck: function (aDownload) {
|
||||
if (this.dontCheckApplicationReputation) {
|
||||
return Promise.resolve(this.shouldBlockInTestForApplicationReputation);
|
||||
return Promise.resolve({
|
||||
shouldBlock: this.shouldBlockInTestForApplicationReputation,
|
||||
verdict: this.verdictInTestForApplicationReputation,
|
||||
});
|
||||
}
|
||||
let hash;
|
||||
let sigInfo;
|
||||
@ -546,10 +570,16 @@ this.DownloadIntegration = {
|
||||
channelRedirects = aDownload.saver.getRedirects();
|
||||
} catch (ex) {
|
||||
// Bail if DownloadSaver doesn't have a hash or signature info.
|
||||
return Promise.resolve(false);
|
||||
return Promise.resolve({
|
||||
shouldBlock: false,
|
||||
verdict: "",
|
||||
});
|
||||
}
|
||||
if (!hash || !sigInfo) {
|
||||
return Promise.resolve(false);
|
||||
return Promise.resolve({
|
||||
shouldBlock: false,
|
||||
verdict: "",
|
||||
});
|
||||
}
|
||||
let deferred = Promise.defer();
|
||||
let aReferrer = null;
|
||||
@ -564,8 +594,11 @@ this.DownloadIntegration = {
|
||||
suggestedFileName: OS.Path.basename(aDownload.target.path),
|
||||
signatureInfo: sigInfo,
|
||||
redirects: channelRedirects },
|
||||
function onComplete(aShouldBlock, aRv) {
|
||||
deferred.resolve(aShouldBlock);
|
||||
function onComplete(aShouldBlock, aRv, aVerdict) {
|
||||
deferred.resolve({
|
||||
shouldBlock: aShouldBlock,
|
||||
verdict: (aShouldBlock && kVerdictMap[aVerdict]) || "",
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
},
|
||||
|
@ -1711,12 +1711,15 @@ add_task(function* test_getSha256Hash()
|
||||
var promiseBlockedDownload = Task.async(function* (options) {
|
||||
function cleanup() {
|
||||
DownloadIntegration.shouldBlockInTestForApplicationReputation = false;
|
||||
DownloadIntegration.verdictInTestForApplicationReputation = "";
|
||||
DownloadIntegration.shouldKeepBlockedDataInTest = false;
|
||||
}
|
||||
do_register_cleanup(cleanup);
|
||||
|
||||
let {keepPartialData, keepBlockedData} = options;
|
||||
DownloadIntegration.shouldBlockInTestForApplicationReputation = true;
|
||||
DownloadIntegration.verdictInTestForApplicationReputation =
|
||||
Downloads.Error.BLOCK_VERDICT_UNCOMMON;
|
||||
DownloadIntegration.shouldKeepBlockedDataInTest = keepBlockedData;
|
||||
|
||||
let download;
|
||||
@ -1740,7 +1743,11 @@ var promiseBlockedDownload = Task.async(function* (options) {
|
||||
throw ex;
|
||||
}
|
||||
do_check_true(ex.becauseBlockedByReputationCheck);
|
||||
do_check_eq(ex.reputationCheckVerdict,
|
||||
Downloads.Error.BLOCK_VERDICT_UNCOMMON);
|
||||
do_check_true(download.error.becauseBlockedByReputationCheck);
|
||||
do_check_eq(download.error.reputationCheckVerdict,
|
||||
Downloads.Error.BLOCK_VERDICT_UNCOMMON);
|
||||
}
|
||||
|
||||
do_check_true(download.stopped);
|
||||
|
Loading…
Reference in New Issue
Block a user