mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
f4ea4e85aa
Implement mozDownloadManager.adoptDownload as a certified-only API. This also fixes and re-enables many of the existing dom/downloads tests failures by virtue of cleanup and not running them on non-gonk toolkits where exceptions will be thrown and things will fail. This should resolve bug 979446 about re-enabling the tests.
219 lines
7.5 KiB
JavaScript
219 lines
7.5 KiB
JavaScript
/**
|
|
* Test the adoptDownload API. Specifically, we expect that when we call
|
|
* adoptDownload with a valid payload that:
|
|
* - The method will be resolved with a valid, fully populated DOMDownload
|
|
* instance, including an id.
|
|
* - An ondownloadstart notification will be generated and the DOMDownload
|
|
* instance it receives will be logically equivalent.
|
|
*
|
|
* We also explicitly verify that invalid adoptDownload payloads result in a
|
|
* rejection and that no download is added.
|
|
*
|
|
* This test explicitly does not test that the download is correctly persisted
|
|
* to the database. This is done because Downloads.jsm does not provide a means
|
|
* of safely restarting itself, so Firefox would need to be restarted. Because
|
|
* the adoptDownload code is using the Downloads API in a straightforward
|
|
* manner, it's not considered likely this would regress, and certainly not
|
|
* considered worth the automated testing overhead of a restart.
|
|
*/
|
|
|
|
function checkInvalidResult(dict, expectedErr, explanation) {
|
|
navigator.mozDownloadManager.ondownloadstart = function() {
|
|
ok(false, "No download should have been added!");
|
|
};
|
|
navigator.mozDownloadManager.adoptDownload(dict).then(
|
|
function() {
|
|
ok(false, "Invalid adoptDownload did not reject!");
|
|
runTests();
|
|
},
|
|
function(rejectedWith) {
|
|
is(rejectedWith, expectedErr, explanation + " rejection value");
|
|
runTests();
|
|
});
|
|
}
|
|
|
|
// Pick a date that Date.now() could not possibly return by picking a date in
|
|
// the past. (We want to make sure the date we provide works.)
|
|
var arbitraryDate = new Date(Date.now() - 60000);
|
|
|
|
var blobContents = new Uint8Array(256);
|
|
var memBlob = new Blob([blobContents], { type: 'application/octet-stream' });
|
|
var blobStorageName;
|
|
var blobStoragePath = 'blobby.blob';
|
|
|
|
function checkAdoptedDownload(download, validPayload) {
|
|
is(download.totalBytes, memBlob.size, 'size');
|
|
is(download.url, validPayload.url, 'url');
|
|
// The filesystem path is not practical to check since we can't hard-code it
|
|
// and the only way to check is to effectively duplicate the logic in
|
|
// DownloadsAPI.js. The good news, however, is that the value is
|
|
// round-tripped from storageName/storagePath to path and back again, and we
|
|
// also verify the file exists on disk, so we can be reasonably confident this
|
|
// is correct. We output it to aid in debugging if things should break,
|
|
// of course.
|
|
info('path (not checked): ' + download.path);
|
|
is(download.storageName, validPayload.storageName, 'storageName');
|
|
is(download.storagePath, validPayload.storagePath, 'storagePath');
|
|
is(download.state, 'succeeded', 'state');
|
|
is(download.contentType, validPayload.contentType, 'contentType');
|
|
is(download.startTime.valueOf(), arbitraryDate.valueOf(), 'startTime');
|
|
is(download.sourceAppManifestURL,
|
|
'http://mochi.test:8888/' +
|
|
'tests/dom/downloads/tests/testapp_downloads_adopt_download.manifest',
|
|
'app manifest');
|
|
};
|
|
|
|
var tests = [
|
|
function saveBlobToDeviceStorage() {
|
|
// Only sdcard can handle arbitrary MIME types and is guaranteed to be a
|
|
// thing.
|
|
var storage = navigator.getDeviceStorage('sdcard');
|
|
// We used the non-array helper, so the name we get may be different than
|
|
// what we asked for.
|
|
blobStorageName = storage.storageName;
|
|
ok(!!storage, 'have storage');
|
|
var req = storage.addNamed(memBlob, blobStoragePath);
|
|
req.onerror = function() {
|
|
ok(false, 'problem saving blob to storage: ' + req.error.name);
|
|
};
|
|
req.onsuccess = function(evt) {
|
|
ok(true, 'saved blob: ' + evt.target.result);
|
|
runTests();
|
|
};
|
|
},
|
|
function addValid() {
|
|
var validPayload = {
|
|
// All currently expected consumers are unable to provide a valid URL, and
|
|
// as a result need to provide an empty string.
|
|
url: "",
|
|
storageName: blobStorageName,
|
|
storagePath: blobStoragePath,
|
|
contentType: memBlob.type,
|
|
startTime: arbitraryDate
|
|
};
|
|
// Wrap the notification in a check so we can force our logic to be
|
|
// consistently ordered in the test even if it's not in reality.
|
|
var notifiedPromise = new Promise(function(resolve, reject) {
|
|
navigator.mozDownloadManager.ondownloadstart = function(evt) {
|
|
resolve(evt.download);
|
|
};
|
|
});
|
|
|
|
// Start the download
|
|
navigator.mozDownloadManager.adoptDownload(validPayload).then(
|
|
function(apiDownload) {
|
|
checkAdoptedDownload(apiDownload, validPayload);
|
|
ok(!!apiDownload.id, "Need a download id!");
|
|
notifiedPromise.then(function(notifiedDownload) {
|
|
checkAdoptedDownload(notifiedDownload, validPayload);
|
|
is(apiDownload.id, notifiedDownload.id,
|
|
"Notification should be for the download we adopted");
|
|
runTests();
|
|
});
|
|
},
|
|
function() {
|
|
ok(false, "adoptDownload should not have rejected");
|
|
runTests();
|
|
});
|
|
},
|
|
|
|
function dictionaryNotProvided() {
|
|
checkInvalidResult(undefined, "InvalidDownload");
|
|
},
|
|
// Missing fields immediately result in rejection with InvalidDownload
|
|
function missingStorageName() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
// no storageName
|
|
storagePath: "relpath/filename.txt",
|
|
contentType: "text/plain",
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "missing storage name");
|
|
},
|
|
function nullStorageName() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: null,
|
|
storagePath: "relpath/filename.txt",
|
|
contentType: "text/plain",
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "null storage name");
|
|
},
|
|
function missingStoragePath() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: blobStorageName,
|
|
// no storagePath
|
|
contentType: "text/plain",
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "missing storage path");
|
|
},
|
|
function nullStoragePath() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: blobStorageName,
|
|
storagePath: null,
|
|
contentType: "text/plain",
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "null storage path");
|
|
},
|
|
function missingContentType() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: "sdcard",
|
|
storagePath: "relpath/filename.txt",
|
|
// no contentType
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "missing content type");
|
|
},
|
|
function nullContentType() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: "sdcard",
|
|
storagePath: "relpath/filename.txt",
|
|
contentType: null,
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "null content type");
|
|
},
|
|
// Incorrect storage names are likewise immediately invalidated
|
|
function invalidStorageName() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: "ALMOST CERTAINLY DOES NOT EXIST",
|
|
storagePath: "relpath/filename.txt",
|
|
contentType: "text/plain",
|
|
startTime: arbitraryDate
|
|
}, "InvalidDownload", "invalid storage name");
|
|
},
|
|
// The existence of the file is validated in the parent process
|
|
function legitStorageInvalidPath() {
|
|
checkInvalidResult({
|
|
url: "",
|
|
storageName: blobStorageName,
|
|
storagePath: "ALMOST CERTAINLY DOES NOT EXIST",
|
|
contentType: "text/plain",
|
|
startTime: arbitraryDate
|
|
}, "AdoptNoSuchFile", "invalid path");
|
|
},
|
|
function allDone() {
|
|
// Just in case, make sure no other mochitest could mess with us after we've
|
|
// finished.
|
|
navigator.mozDownloadManager.ondownloadstart = null;
|
|
runTests();
|
|
}
|
|
];
|
|
|
|
function runTests() {
|
|
if (!tests.length) {
|
|
finish();
|
|
return;
|
|
}
|
|
|
|
var test = tests.shift();
|
|
if (test.name) {
|
|
info('starting test: ' + test.name);
|
|
}
|
|
test();
|
|
}
|
|
runTests();
|