зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1576333 - Part 1: Allow Downloads users to inspect HTTP codes r=mak
Differential Revision: https://phabricator.services.mozilla.com/D43342 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e3584dcd2b
Коммит
37528b94d0
|
@ -1329,6 +1329,23 @@ this.DownloadSource.prototype = {
|
|||
*/
|
||||
adjustChannel: null,
|
||||
|
||||
/**
|
||||
* For downloads handled by the (default) DownloadCopySaver, this function
|
||||
* will determine, if provided, if a download can progress or has to be
|
||||
* cancelled based on the HTTP status code of the network channel.
|
||||
*
|
||||
* @note If this is defined this object will not be serializable, thus the
|
||||
* Download object will not be persisted across sessions.
|
||||
*
|
||||
* @param aDownload
|
||||
* The download asking.
|
||||
* @param aStatus
|
||||
* The HTTP status in question
|
||||
*
|
||||
* @return {Boolean} Download can progress
|
||||
*/
|
||||
allowHttpStatus: null,
|
||||
|
||||
/**
|
||||
* Returns a static representation of the current object state.
|
||||
*
|
||||
|
@ -1340,6 +1357,11 @@ this.DownloadSource.prototype = {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (this.allowHttpStatus) {
|
||||
// If the callback was used, we can't reproduce this across sessions.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Simplify the representation if we don't have other details.
|
||||
if (!this.isPrivate && !this.referrerInfo && !this._unknownProperties) {
|
||||
return this.url;
|
||||
|
@ -1381,6 +1403,11 @@ this.DownloadSource.prototype = {
|
|||
* this function can adjust the network channel before
|
||||
* it is opened, for example to change the HTTP headers
|
||||
* or to upload a stream as POST data. Optional.
|
||||
* allowHttpStatus: For downloads handled by the (default)
|
||||
* DownloadCopySaver, this function will determine, if
|
||||
* provided, if a download can progress or has to be
|
||||
* cancelled based on the HTTP status code of the
|
||||
* network channel.
|
||||
* }
|
||||
*
|
||||
* @return The newly created DownloadSource object.
|
||||
|
@ -1419,6 +1446,10 @@ this.DownloadSource.fromSerializable = function(aSerializable) {
|
|||
source.adjustChannel = aSerializable.adjustChannel;
|
||||
}
|
||||
|
||||
if ("allowHttpStatus" in aSerializable) {
|
||||
source.allowHttpStatus = aSerializable.allowHttpStatus;
|
||||
}
|
||||
|
||||
deserializeUnknownProperties(
|
||||
source,
|
||||
aSerializable,
|
||||
|
@ -2103,6 +2134,19 @@ this.DownloadCopySaver.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check back with the initiator if we should allow a certain
|
||||
// HTTP code. By default, we'll just save error pages too,
|
||||
// however a consumer down the line, such as the WebExtensions
|
||||
// downloads API might want to handle this differently.
|
||||
if (
|
||||
download.source.allowHttpStatus &&
|
||||
aRequest instanceof Ci.nsIHttpChannel &&
|
||||
!download.source.allowHttpStatus(download, aRequest.responseStatus)
|
||||
) {
|
||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
aSetPropertiesFn({ contentType: channel.contentType });
|
||||
|
||||
// Ensure we report the value of "Content-Length", if available,
|
||||
|
|
|
@ -916,6 +916,13 @@ add_task(function test_common_initialize() {
|
|||
}
|
||||
);
|
||||
|
||||
gHttpServer.registerPathHandler("/busy.txt", function(aRequest, aResponse) {
|
||||
aResponse.setStatusLine("1.1", 504, "Gateway Timeout");
|
||||
aResponse.setHeader("Content-Type", "text/plain", false);
|
||||
aResponse.setHeader("Content-Length", "" + TEST_DATA_SHORT.length, false);
|
||||
aResponse.write(TEST_DATA_SHORT);
|
||||
});
|
||||
|
||||
// This URL will emulate being blocked by Windows Parental controls
|
||||
gHttpServer.registerPathHandler("/parentalblocked.zip", function(
|
||||
aRequest,
|
||||
|
|
|
@ -46,6 +46,80 @@ add_task(async function test_error_target_downloadingToSameFile() {
|
|||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests allowHttpStatus allowing requests
|
||||
*/
|
||||
add_task(async function test_error_notfound() {
|
||||
const targetFile = getTempFile(TEST_TARGET_FILE_NAME);
|
||||
let called = false;
|
||||
const download = await Downloads.createDownload({
|
||||
source: {
|
||||
url: httpUrl("notfound.gone"),
|
||||
allowHttpStatus(aDownload, aStatusCode) {
|
||||
Assert.strictEqual(download, aDownload, "Check Download objects");
|
||||
Assert.strictEqual(aStatusCode, 404, "The status should be correct");
|
||||
called = true;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
target: targetFile,
|
||||
});
|
||||
await download.start();
|
||||
Assert.ok(called, "allowHttpStatus should have been called");
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests allowHttpStatus rejecting requests
|
||||
*/
|
||||
add_task(async function test_error_notfound_reject() {
|
||||
const targetFile = getTempFile(TEST_TARGET_FILE_NAME);
|
||||
let called = false;
|
||||
const download = await Downloads.createDownload({
|
||||
source: {
|
||||
url: httpUrl("notfound.gone"),
|
||||
allowHttpStatus(aDownload, aStatusCode) {
|
||||
Assert.strictEqual(download, aDownload, "Check Download objects");
|
||||
Assert.strictEqual(aStatusCode, 404, "The status should be correct");
|
||||
called = true;
|
||||
return false;
|
||||
},
|
||||
},
|
||||
target: targetFile,
|
||||
});
|
||||
await Assert.rejects(
|
||||
download.start(),
|
||||
ex => ex instanceof Downloads.Error && ex.becauseSourceFailed,
|
||||
"Download should have been rejected"
|
||||
);
|
||||
Assert.ok(called, "allowHttpStatus should have been called");
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests allowHttpStatus rejecting requests other than 404
|
||||
*/
|
||||
add_task(async function test_error_busy_reject() {
|
||||
const targetFile = getTempFile(TEST_TARGET_FILE_NAME);
|
||||
let called = false;
|
||||
const download = await Downloads.createDownload({
|
||||
source: {
|
||||
url: httpUrl("busy.txt"),
|
||||
allowHttpStatus(aDownload, aStatusCode) {
|
||||
Assert.strictEqual(download, aDownload, "Check Download objects");
|
||||
Assert.strictEqual(aStatusCode, 504, "The status should be correct");
|
||||
called = true;
|
||||
return false;
|
||||
},
|
||||
},
|
||||
target: targetFile,
|
||||
});
|
||||
await Assert.rejects(
|
||||
download.start(),
|
||||
ex => ex instanceof Downloads.Error && ex.becauseSourceFailed,
|
||||
"Download should have been rejected"
|
||||
);
|
||||
Assert.ok(called, "allowHttpStatus should have been called");
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests the DownloadError object.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче