diff options
Diffstat (limited to 'toolkit/components/places/tests/unit/test_download_history.js')
-rw-r--r-- | toolkit/components/places/tests/unit/test_download_history.js | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/unit/test_download_history.js b/toolkit/components/places/tests/unit/test_download_history.js new file mode 100644 index 000000000..643360b20 --- /dev/null +++ b/toolkit/components/places/tests/unit/test_download_history.js @@ -0,0 +1,283 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * This file tests the nsIDownloadHistory Places implementation. + */ + +XPCOMUtils.defineLazyServiceGetter(this, "gDownloadHistory", + "@mozilla.org/browser/download-history;1", + "nsIDownloadHistory"); + +const DOWNLOAD_URI = NetUtil.newURI("http://www.example.com/"); +const REFERRER_URI = NetUtil.newURI("http://www.example.org/"); +const PRIVATE_URI = NetUtil.newURI("http://www.example.net/"); + +/** + * Waits for the first visit notification to be received. + * + * @param aCallback + * Callback function to be called with the same arguments of onVisit. + */ +function waitForOnVisit(aCallback) { + let historyObserver = { + __proto__: NavHistoryObserver.prototype, + onVisit: function HO_onVisit() { + PlacesUtils.history.removeObserver(this); + aCallback.apply(null, arguments); + } + }; + PlacesUtils.history.addObserver(historyObserver, false); +} + +/** + * Waits for the first onDeleteURI notification to be received. + * + * @param aCallback + * Callback function to be called with the same arguments of onDeleteURI. + */ +function waitForOnDeleteURI(aCallback) { + let historyObserver = { + __proto__: NavHistoryObserver.prototype, + onDeleteURI: function HO_onDeleteURI() { + PlacesUtils.history.removeObserver(this); + aCallback.apply(null, arguments); + } + }; + PlacesUtils.history.addObserver(historyObserver, false); +} + +/** + * Waits for the first onDeleteVisits notification to be received. + * + * @param aCallback + * Callback function to be called with the same arguments of onDeleteVisits. + */ +function waitForOnDeleteVisits(aCallback) { + let historyObserver = { + __proto__: NavHistoryObserver.prototype, + onDeleteVisits: function HO_onDeleteVisits() { + PlacesUtils.history.removeObserver(this); + aCallback.apply(null, arguments); + } + }; + PlacesUtils.history.addObserver(historyObserver, false); +} + +function run_test() +{ + run_next_test(); +} + +add_test(function test_dh_is_from_places() +{ + // Test that this nsIDownloadHistory is the one places implements. + do_check_true(gDownloadHistory instanceof Ci.mozIAsyncHistory); + + run_next_test(); +}); + +add_test(function test_dh_addRemoveDownload() +{ + waitForOnVisit(function DHAD_onVisit(aURI) { + do_check_true(aURI.equals(DOWNLOAD_URI)); + + // Verify that the URI is already available in results at this time. + do_check_true(!!page_in_database(DOWNLOAD_URI)); + + waitForOnDeleteURI(function DHRAD_onDeleteURI(aDeletedURI) { + do_check_true(aDeletedURI.equals(DOWNLOAD_URI)); + + // Verify that the URI is already available in results at this time. + do_check_false(!!page_in_database(DOWNLOAD_URI)); + + run_next_test(); + }); + gDownloadHistory.removeAllDownloads(); + }); + + gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000); +}); + +add_test(function test_dh_addMultiRemoveDownload() +{ + PlacesTestUtils.addVisits({ + uri: DOWNLOAD_URI, + transition: TRANSITION_TYPED + }).then(function () { + waitForOnVisit(function DHAD_onVisit(aURI) { + do_check_true(aURI.equals(DOWNLOAD_URI)); + do_check_true(!!page_in_database(DOWNLOAD_URI)); + + waitForOnDeleteVisits(function DHRAD_onDeleteVisits(aDeletedURI) { + do_check_true(aDeletedURI.equals(DOWNLOAD_URI)); + do_check_true(!!page_in_database(DOWNLOAD_URI)); + + PlacesTestUtils.clearHistory().then(run_next_test); + }); + gDownloadHistory.removeAllDownloads(); + }); + + gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000); + }); +}); + +add_test(function test_dh_addBookmarkRemoveDownload() +{ + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + DOWNLOAD_URI, + PlacesUtils.bookmarks.DEFAULT_INDEX, + "A bookmark"); + waitForOnVisit(function DHAD_onVisit(aURI) { + do_check_true(aURI.equals(DOWNLOAD_URI)); + do_check_true(!!page_in_database(DOWNLOAD_URI)); + + waitForOnDeleteVisits(function DHRAD_onDeleteVisits(aDeletedURI) { + do_check_true(aDeletedURI.equals(DOWNLOAD_URI)); + do_check_true(!!page_in_database(DOWNLOAD_URI)); + + PlacesTestUtils.clearHistory().then(run_next_test); + }); + gDownloadHistory.removeAllDownloads(); + }); + + gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000); +}); + +add_test(function test_dh_addDownload_referrer() +{ + waitForOnVisit(function DHAD_prepareReferrer(aURI, aVisitID) { + do_check_true(aURI.equals(REFERRER_URI)); + let referrerVisitId = aVisitID; + + waitForOnVisit(function DHAD_onVisit(aVisitedURI, unused, unused2, unused3, + aReferringID) { + do_check_true(aVisitedURI.equals(DOWNLOAD_URI)); + do_check_eq(aReferringID, referrerVisitId); + + // Verify that the URI is already available in results at this time. + do_check_true(!!page_in_database(DOWNLOAD_URI)); + + PlacesTestUtils.clearHistory().then(run_next_test); + }); + + gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000); + }); + + // Note that we don't pass the optional callback argument here because we must + // ensure that we receive the onVisit notification before we call addDownload. + PlacesUtils.asyncHistory.updatePlaces({ + uri: REFERRER_URI, + visits: [{ + transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED, + visitDate: Date.now() * 1000 + }] + }); +}); + +add_test(function test_dh_addDownload_disabledHistory() +{ + waitForOnVisit(function DHAD_onVisit(aURI) { + // We should only receive the notification for the non-private URI. This + // test is based on the assumption that visit notifications are received in + // the same order of the addDownload calls, which is currently true because + // database access is serialized on the same worker thread. + do_check_true(aURI.equals(DOWNLOAD_URI)); + + do_check_true(!!page_in_database(DOWNLOAD_URI)); + do_check_false(!!page_in_database(PRIVATE_URI)); + + PlacesTestUtils.clearHistory().then(run_next_test); + }); + + Services.prefs.setBoolPref("places.history.enabled", false); + gDownloadHistory.addDownload(PRIVATE_URI, REFERRER_URI, Date.now() * 1000); + + // The addDownload functions calls CanAddURI synchronously, thus we can set + // the preference back to true immediately (not all apps enable places by + // default). + Services.prefs.setBoolPref("places.history.enabled", true); + gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000); +}); + +/** + * Tests that nsIDownloadHistory::AddDownload saves the additional download + * details if the optional destination URL is specified. + */ +add_test(function test_dh_details() +{ + const REMOTE_URI = NetUtil.newURI("http://localhost/"); + const SOURCE_URI = NetUtil.newURI("http://example.com/test_dh_details"); + const DEST_FILE_NAME = "dest.txt"; + + // We must build a real, valid file URI for the destination. + let destFileUri = NetUtil.newURI(FileUtils.getFile("TmpD", [DEST_FILE_NAME])); + + let titleSet = false; + let destinationFileUriSet = false; + let destinationFileNameSet = false; + + function checkFinished() + { + if (titleSet && destinationFileUriSet && destinationFileNameSet) { + PlacesUtils.annotations.removeObserver(annoObserver); + PlacesUtils.history.removeObserver(historyObserver); + + PlacesTestUtils.clearHistory().then(run_next_test); + } + } + + let annoObserver = { + onPageAnnotationSet: function AO_onPageAnnotationSet(aPage, aName) + { + if (aPage.equals(SOURCE_URI)) { + let value = PlacesUtils.annotations.getPageAnnotation(aPage, aName); + switch (aName) + { + case "downloads/destinationFileURI": + destinationFileUriSet = true; + do_check_eq(value, destFileUri.spec); + break; + case "downloads/destinationFileName": + destinationFileNameSet = true; + do_check_eq(value, DEST_FILE_NAME); + break; + } + checkFinished(); + } + }, + onItemAnnotationSet: function() {}, + onPageAnnotationRemoved: function() {}, + onItemAnnotationRemoved: function() {} + } + + let historyObserver = { + onBeginUpdateBatch: function() {}, + onEndUpdateBatch: function() {}, + onVisit: function() {}, + onTitleChanged: function HO_onTitleChanged(aURI, aPageTitle) + { + if (aURI.equals(SOURCE_URI)) { + titleSet = true; + do_check_eq(aPageTitle, DEST_FILE_NAME); + checkFinished(); + } + }, + onDeleteURI: function() {}, + onClearHistory: function() {}, + onPageChanged: function() {}, + onDeleteVisits: function() {} + }; + + PlacesUtils.annotations.addObserver(annoObserver, false); + PlacesUtils.history.addObserver(historyObserver, false); + + // Both null values and remote URIs should not cause errors. + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000); + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, null); + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, REMOTE_URI); + + // Valid local file URIs should cause the download details to be saved. + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, + destFileUri); +}); |