summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/unit/test_download_history.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/unit/test_download_history.js')
-rw-r--r--toolkit/components/places/tests/unit/test_download_history.js283
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);
+});