Bug 836485 - Add methods to remove downloads on history expiration r=paolo

This commit is contained in:
Raymond Lee 2013-06-22 02:35:09 +08:00
parent e4dc30bf22
commit c9ea400e18
4 changed files with 194 additions and 3 deletions

View File

@ -25,8 +25,12 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
////////////////////////////////////////////////////////////////////////////////
//// DownloadList
@ -34,10 +38,18 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise",
/**
* Represents a collection of Download objects that can be viewed and managed by
* the user interface, and persisted across sessions.
*
* @param aIsPublic
* The boolean indicates it's a public download list or not.
*/
function DownloadList() {
function DownloadList(aIsPublic) {
this._downloads = [];
this._views = new Set();
// Only need to remove history entries for public downloads as no history
// entries are added for private downloads.
if (aIsPublic) {
PlacesUtils.history.addObserver(this, false);
}
}
DownloadList.prototype = {
@ -179,4 +191,61 @@ DownloadList.prototype = {
{
this._views.delete(aView);
},
/**
* Removes downloads from the list based on the given test function.
*
* @param aTestFn
* The test function.
*/
_removeWhere: function DL__removeWhere(aTestFn) {
Task.spawn(function() {
let list = yield this.getAll();
for (let download of list) {
// Remove downloads that have been canceled, even if the cancellation
// operation hasn't completed yet so we don't check "stopped" here.
if ((download.succeeded || download.canceled || download.error) &&
aTestFn(download)) {
this.remove(download);
}
}
}.bind(this)).then(null, Cu.reportError);
},
/**
* Removes downloads within the given period of time.
*
* @param aStartTime
* The start time date object.
* @param aEndTime
* The end time date object.
*/
removeByTimeframe: function DL_removeByTimeframe(aStartTime, aEndTime) {
this._removeWhere(download => download.startTime >= aStartTime &&
download.startTime <= aEndTime);
},
////////////////////////////////////////////////////////////////////////////
//// nsISupports
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver]),
////////////////////////////////////////////////////////////////////////////
//// nsINavHistoryObserver
onDeleteURI: function DL_onDeleteURI(aURI, aGUID) {
this._removeWhere(download => aURI.equals(download.source.uri));
},
onClearHistory: function DL_onClearHistory() {
this._removeWhere(() => true);
},
onTitleChanged: function () {},
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
};

View File

@ -174,7 +174,7 @@ this.Downloads = {
getPublicDownloadList: function D_getPublicDownloadList()
{
if (!this._publicDownloadList) {
this._publicDownloadList = new DownloadList();
this._publicDownloadList = new DownloadList(true);
}
return Promise.resolve(this._publicDownloadList);
},
@ -193,7 +193,7 @@ this.Downloads = {
getPrivateDownloadList: function D_getPrivateDownloadList()
{
if (!this._privateDownloadList) {
this._privateDownloadList = new DownloadList();
this._privateDownloadList = new DownloadList(false);
}
return Promise.resolve(this._privateDownloadList);
},

View File

@ -31,6 +31,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
"resource://testing-common/httpd.js");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
@ -89,6 +91,7 @@ const TEST_DATA_SHORT_GZIP_ENCODED =
*/
function run_test()
{
do_get_profile();
run_next_test();
}
@ -212,6 +215,39 @@ function promiseVerifyContents(aFile, aExpectedContents)
return deferred.promise;
}
/**
* Adds entry for download.
*
* @param aSourceURI
* The nsIURI for the download source, or null to use TEST_SOURCE_URI.
*
* @return {Promise}
* @rejects JavaScript exception.
*/
function promiseAddDownloadToHistory(aSourceURI) {
let deferred = Promise.defer();
PlacesUtils.asyncHistory.updatePlaces(
{
uri: aSourceURI || TEST_SOURCE_URI,
visits: [{
transitionType: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD,
visitDate: Date.now()
}]
},
{
handleError: function handleError(aResultCode, aPlaceInfo) {
let ex = new Components.Exception("Unexpected error in adding visits.",
aResultCode);
deferred.reject(ex);
},
handleResult: function () {},
handleCompletion: function handleCompletion() {
deferred.resolve();
}
});
return deferred.promise;
}
/**
* Starts a socket listener that closes each incoming connection.
*

View File

@ -187,3 +187,89 @@ add_task(function test_notifications_change()
yield downloadTwo.start();
do_check_false(receivedOnDownloadChanged);
});
/**
* Checks that download is removed on history expiration.
*/
add_task(function test_history_expiration()
{
function cleanup() {
Services.prefs.clearUserPref("places.history.expiration.max_pages");
}
do_register_cleanup(cleanup);
// Set max pages to 0 to make the download expire.
Services.prefs.setIntPref("places.history.expiration.max_pages", 0);
// Add expirable visit for downloads.
yield promiseAddDownloadToHistory();
yield promiseAddDownloadToHistory(TEST_INTERRUPTIBLE_URI);
let list = yield promiseNewDownloadList();
let downloadOne = yield promiseSimpleDownload();
let downloadTwo = yield promiseSimpleDownload(TEST_INTERRUPTIBLE_URI);
list.add(downloadOne);
list.add(downloadTwo);
let deferred = Promise.defer();
let removeNotifications = 0;
let downloadView = {
onDownloadRemoved: function (aDownload) {
if (++removeNotifications == 2) {
deferred.resolve();
}
},
};
list.addView(downloadView);
// Start download one.
yield downloadOne.start();
// Start download two and then cancel it.
downloadTwo.start();
let promiseCanceled = downloadTwo.cancel();
// Force a history expiration.
let expire = Cc["@mozilla.org/places/expiration;1"]
.getService(Ci.nsIObserver);
expire.observe(null, "places-debug-start-expiration", -1);
yield deferred.promise;
yield promiseCanceled;
cleanup();
});
/**
* Checks all downloads are removed after clearing history.
*/
add_task(function test_history_clear()
{
// Add expirable visit for downloads.
yield promiseAddDownloadToHistory();
yield promiseAddDownloadToHistory();
let list = yield promiseNewDownloadList();
let downloadOne = yield promiseSimpleDownload();
let downloadTwo = yield promiseSimpleDownload();
list.add(downloadOne);
list.add(downloadTwo);
let deferred = Promise.defer();
let removeNotifications = 0;
let downloadView = {
onDownloadRemoved: function (aDownload) {
if (++removeNotifications == 2) {
deferred.resolve();
}
},
};
list.addView(downloadView);
yield downloadOne.start();
yield downloadTwo.start();
PlacesUtils.history.removeAllPages();
yield deferred.promise;
});