mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-11 13:48:23 +02:00
***
Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8
This changes the behavior of ChromeUtils.import() to return an exports object,
rather than a module global, in all cases except when `null` is passed as a
second argument, and changes the default behavior not to pollute the global
scope with the module's exports. Thus, the following code written for the old
model:
ChromeUtils.import("resource://gre/modules/Services.jsm");
is approximately the same as the following, in the new model:
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Since the two behaviors are mutually incompatible, this patch will land with a
scripted rewrite to update all existing callers to use the new model rather
than the old.
***
Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs
This was done using the followng script:
https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm
***
Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D16747
***
Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16748
***
Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16749
***
Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs
***
Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16750
--HG--
extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895
extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
241 lines
9.3 KiB
JavaScript
241 lines
9.3 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
/**
|
|
* Tests the DownloadHistory module.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const {DownloadHistory} = ChromeUtils.import("resource://gre/modules/DownloadHistory.jsm");
|
|
|
|
let baseDate = new Date("2000-01-01");
|
|
|
|
/**
|
|
* Non-fatal assertion used to test whether the downloads in the list already
|
|
* match the expected state.
|
|
*/
|
|
function areEqual(a, b) {
|
|
if (a === b) {
|
|
Assert.equal(a, b);
|
|
return true;
|
|
}
|
|
info(a + " !== " + b);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This allows waiting for an expected list at various points during the test.
|
|
*/
|
|
class TestView {
|
|
constructor(expected) {
|
|
this.expected = [...expected];
|
|
this.downloads = [];
|
|
this.resolveWhenExpected = () => {};
|
|
}
|
|
onDownloadAdded(download, options = {}) {
|
|
if (options.insertBefore) {
|
|
let index = this.downloads.indexOf(options.insertBefore);
|
|
this.downloads.splice(index, 0, download);
|
|
} else {
|
|
this.downloads.push(download);
|
|
}
|
|
this.checkForExpectedDownloads();
|
|
}
|
|
onDownloadChanged(download) {
|
|
this.checkForExpectedDownloads();
|
|
}
|
|
onDownloadRemoved(download) {
|
|
let index = this.downloads.indexOf(download);
|
|
this.downloads.splice(index, 1);
|
|
this.checkForExpectedDownloads();
|
|
}
|
|
checkForExpectedDownloads() {
|
|
// Wait for all the expected downloads to be added or removed before doing
|
|
// the detailed tests. This is done to avoid creating irrelevant output.
|
|
if (this.downloads.length != this.expected.length) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < this.downloads.length; i++) {
|
|
if (this.downloads[i].source.url != this.expected[i].source.url ||
|
|
this.downloads[i].target.path != this.expected[i].target.path) {
|
|
return;
|
|
}
|
|
}
|
|
// Check and report the actual state of the downloads. Even if the items
|
|
// are in the expected order, the metadata for history downloads might not
|
|
// have been updated to the final state yet.
|
|
for (let i = 0; i < this.downloads.length; i++) {
|
|
let download = this.downloads[i];
|
|
let testDownload = this.expected[i];
|
|
info("Checking download source " + download.source.url +
|
|
" with target " + download.target.path);
|
|
if (!areEqual(download.succeeded, !!testDownload.succeeded) ||
|
|
!areEqual(download.canceled, !!testDownload.canceled) ||
|
|
!areEqual(download.hasPartialData, !!testDownload.hasPartialData) ||
|
|
!areEqual(!!download.error, !!testDownload.error)) {
|
|
return;
|
|
}
|
|
// If the above properties match, the error details should be correct.
|
|
if (download.error) {
|
|
if (testDownload.error.becauseSourceFailed) {
|
|
Assert.equal(download.error.message, "History download failed.");
|
|
}
|
|
Assert.equal(download.error.becauseBlockedByParentalControls,
|
|
testDownload.error.becauseBlockedByParentalControls);
|
|
Assert.equal(download.error.becauseBlockedByReputationCheck,
|
|
testDownload.error.becauseBlockedByReputationCheck);
|
|
}
|
|
}
|
|
this.resolveWhenExpected();
|
|
}
|
|
async waitForExpected() {
|
|
let promise = new Promise(resolve => this.resolveWhenExpected = resolve);
|
|
this.checkForExpectedDownloads();
|
|
await promise;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests that various operations on session and history downloads are reflected
|
|
* by the DownloadHistoryList object, and that the order of results is correct.
|
|
*/
|
|
add_task(async function test_DownloadHistory() {
|
|
// Clean up at the beginning and at the end of the test.
|
|
async function cleanup() {
|
|
await PlacesUtils.history.clear();
|
|
}
|
|
registerCleanupFunction(cleanup);
|
|
await cleanup();
|
|
|
|
let testDownloads = [
|
|
// History downloads should appear in order at the beginning of the list.
|
|
{ offset: 10, canceled: true },
|
|
{ offset: 20, succeeded: true },
|
|
{ offset: 30, error: { becauseSourceFailed: true } },
|
|
{ offset: 40, error: { becauseBlockedByParentalControls: true } },
|
|
{ offset: 50, error: { becauseBlockedByReputationCheck: true } },
|
|
// Session downloads should show up after all the history download, in the
|
|
// same order as they were added.
|
|
{ offset: 45, canceled: true, inSession: true },
|
|
{ offset: 35, canceled: true, hasPartialData: true, inSession: true },
|
|
{ offset: 55, succeeded: true, inSession: true },
|
|
];
|
|
const NEXT_OFFSET = 60;
|
|
|
|
let publicList = await promiseNewList();
|
|
let allList = await Downloads.getList(Downloads.ALL);
|
|
|
|
async function addTestDownload(properties) {
|
|
properties.source = {
|
|
url: httpUrl("source" + properties.offset),
|
|
isPrivate: properties.isPrivate,
|
|
};
|
|
let targetFile = getTempFile(TEST_TARGET_FILE_NAME + properties.offset);
|
|
properties.target = { path: targetFile.path };
|
|
properties.startTime = new Date(baseDate.getTime() + properties.offset);
|
|
|
|
let download = await Downloads.createDownload(properties);
|
|
if (properties.inSession) {
|
|
await allList.add(download);
|
|
}
|
|
|
|
if (properties.isPrivate) {
|
|
return;
|
|
}
|
|
|
|
// Add the download to history using the XPCOM service, then use the
|
|
// DownloadHistory module to save the associated metadata.
|
|
let promiseFileAnnotation = waitForAnnotation(properties.source.url, "downloads/destinationFileURI");
|
|
let promiseMetaAnnotation = waitForAnnotation(properties.source.url, "downloads/metaData");
|
|
let promiseVisit = promiseWaitForVisit(properties.source.url);
|
|
await DownloadHistory.addDownloadToHistory(download);
|
|
await promiseVisit;
|
|
await DownloadHistory.updateMetaData(download);
|
|
await Promise.all([promiseFileAnnotation, promiseMetaAnnotation]);
|
|
}
|
|
|
|
// Add all the test downloads to history.
|
|
for (let properties of testDownloads) {
|
|
await addTestDownload(properties);
|
|
}
|
|
|
|
// Initialize DownloadHistoryList only after having added the history and
|
|
// session downloads, and check that they are loaded in the correct order.
|
|
let historyList = await DownloadHistory.getList();
|
|
let view = new TestView(testDownloads);
|
|
await historyList.addView(view);
|
|
await view.waitForExpected();
|
|
|
|
// Remove a download from history and verify that the change is reflected.
|
|
let downloadToRemove = view.expected[1];
|
|
view.expected.splice(1, 1);
|
|
await PlacesUtils.history.remove(downloadToRemove.source.url);
|
|
await view.waitForExpected();
|
|
|
|
// Add a download to history and verify it's placed before session downloads,
|
|
// even if the start date is more recent.
|
|
let downloadToAdd = { offset: NEXT_OFFSET, canceled: true };
|
|
view.expected.splice(view.expected.findIndex(d => d.inSession), 0,
|
|
downloadToAdd);
|
|
await addTestDownload(downloadToAdd);
|
|
await view.waitForExpected();
|
|
|
|
// Add a session download and verify it's placed after all session downloads,
|
|
// even if the start date is less recent.
|
|
let sessionDownloadToAdd = { offset: 0, inSession: true, succeeded: true };
|
|
view.expected.push(sessionDownloadToAdd);
|
|
await addTestDownload(sessionDownloadToAdd);
|
|
await view.waitForExpected();
|
|
|
|
// Add a session download for the same URI without a history entry, and verify
|
|
// it's visible and placed after all session downloads.
|
|
view.expected.push(sessionDownloadToAdd);
|
|
await publicList.add(await Downloads.createDownload(sessionDownloadToAdd));
|
|
await view.waitForExpected();
|
|
|
|
// Create a new DownloadHistoryList that also shows private downloads. Since
|
|
// we only have public downloads, the two lists should contain the same items.
|
|
let allHistoryList = await DownloadHistory.getList({ type: Downloads.ALL });
|
|
let allView = new TestView(view.expected);
|
|
await allHistoryList.addView(allView);
|
|
await allView.waitForExpected();
|
|
|
|
// Add a new private download and verify it appears only on the complete list.
|
|
let privateDownloadToAdd = { offset: NEXT_OFFSET + 10, inSession: true,
|
|
succeeded: true, isPrivate: true };
|
|
allView.expected.push(privateDownloadToAdd);
|
|
await addTestDownload(privateDownloadToAdd);
|
|
await view.waitForExpected();
|
|
await allView.waitForExpected();
|
|
|
|
// Now test the maxHistoryResults parameter.
|
|
let allHistoryList2 = await DownloadHistory.getList({ type: Downloads.ALL,
|
|
maxHistoryResults: 3 });
|
|
// Prepare the set of downloads to contain fewer history downloads by removing
|
|
// the oldest ones.
|
|
let allView2 = new TestView(allView.expected.slice(3));
|
|
await allHistoryList2.addView(allView2);
|
|
await allView2.waitForExpected();
|
|
|
|
// Create a dummy list and view like the previous limited one to just add and
|
|
// remove its view to make sure it doesn't break other lists' updates.
|
|
let dummyList = await DownloadHistory.getList({ type: Downloads.ALL,
|
|
maxHistoryResults: 3 });
|
|
let dummyView = new TestView([]);
|
|
await dummyList.addView(dummyView);
|
|
await dummyList.removeView(dummyView);
|
|
|
|
// Clear history and check that session downloads with partial data remain.
|
|
// Private downloads are also not cleared when clearing history.
|
|
view.expected = view.expected.filter(d => d.hasPartialData);
|
|
allView.expected = allView.expected.filter(d => d.hasPartialData ||
|
|
d.isPrivate);
|
|
await PlacesUtils.history.clear();
|
|
await view.waitForExpected();
|
|
await allView.waitForExpected();
|
|
|
|
// Check that the dummy view above did not prevent the limited from updating.
|
|
allView2.expected = allView.expected;
|
|
await allView2.waitForExpected();
|
|
});
|