1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/places/tests/unit/test_download_history.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,281 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +/** 1.8 + * This file tests the nsIDownloadHistory Places implementation. 1.9 + */ 1.10 + 1.11 +XPCOMUtils.defineLazyServiceGetter(this, "gDownloadHistory", 1.12 + "@mozilla.org/browser/download-history;1", 1.13 + "nsIDownloadHistory"); 1.14 + 1.15 +const DOWNLOAD_URI = NetUtil.newURI("http://www.example.com/"); 1.16 +const REFERRER_URI = NetUtil.newURI("http://www.example.org/"); 1.17 +const PRIVATE_URI = NetUtil.newURI("http://www.example.net/"); 1.18 + 1.19 +/** 1.20 + * Waits for the first visit notification to be received. 1.21 + * 1.22 + * @param aCallback 1.23 + * Callback function to be called with the same arguments of onVisit. 1.24 + */ 1.25 +function waitForOnVisit(aCallback) { 1.26 + let historyObserver = { 1.27 + __proto__: NavHistoryObserver.prototype, 1.28 + onVisit: function HO_onVisit() { 1.29 + PlacesUtils.history.removeObserver(this); 1.30 + aCallback.apply(null, arguments); 1.31 + } 1.32 + }; 1.33 + PlacesUtils.history.addObserver(historyObserver, false); 1.34 +} 1.35 + 1.36 +/** 1.37 + * Waits for the first onDeleteURI notification to be received. 1.38 + * 1.39 + * @param aCallback 1.40 + * Callback function to be called with the same arguments of onDeleteURI. 1.41 + */ 1.42 +function waitForOnDeleteURI(aCallback) { 1.43 + let historyObserver = { 1.44 + __proto__: NavHistoryObserver.prototype, 1.45 + onDeleteURI: function HO_onDeleteURI() { 1.46 + PlacesUtils.history.removeObserver(this); 1.47 + aCallback.apply(null, arguments); 1.48 + } 1.49 + }; 1.50 + PlacesUtils.history.addObserver(historyObserver, false); 1.51 +} 1.52 + 1.53 +/** 1.54 + * Waits for the first onDeleteVisits notification to be received. 1.55 + * 1.56 + * @param aCallback 1.57 + * Callback function to be called with the same arguments of onDeleteVisits. 1.58 + */ 1.59 +function waitForOnDeleteVisits(aCallback) { 1.60 + let historyObserver = { 1.61 + __proto__: NavHistoryObserver.prototype, 1.62 + onDeleteVisits: function HO_onDeleteVisits() { 1.63 + PlacesUtils.history.removeObserver(this); 1.64 + aCallback.apply(null, arguments); 1.65 + } 1.66 + }; 1.67 + PlacesUtils.history.addObserver(historyObserver, false); 1.68 +} 1.69 + 1.70 +function run_test() 1.71 +{ 1.72 + run_next_test(); 1.73 +} 1.74 + 1.75 +add_test(function test_dh_is_from_places() 1.76 +{ 1.77 + // Test that this nsIDownloadHistory is the one places implements. 1.78 + do_check_true(gDownloadHistory instanceof Ci.mozIAsyncHistory); 1.79 + 1.80 + run_next_test(); 1.81 +}); 1.82 + 1.83 +add_test(function test_dh_addRemoveDownload() 1.84 +{ 1.85 + waitForOnVisit(function DHAD_onVisit(aURI) { 1.86 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.87 + 1.88 + // Verify that the URI is already available in results at this time. 1.89 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.90 + 1.91 + waitForOnDeleteURI(function DHRAD_onDeleteURI(aURI) { 1.92 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.93 + 1.94 + // Verify that the URI is already available in results at this time. 1.95 + do_check_false(!!page_in_database(DOWNLOAD_URI)); 1.96 + 1.97 + run_next_test(); 1.98 + }); 1.99 + gDownloadHistory.removeAllDownloads(); 1.100 + }); 1.101 + 1.102 + gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000); 1.103 +}); 1.104 + 1.105 +add_test(function test_dh_addMultiRemoveDownload() 1.106 +{ 1.107 + promiseAddVisits({ uri: DOWNLOAD_URI, 1.108 + transition: TRANSITION_TYPED }).then(function () { 1.109 + waitForOnVisit(function DHAD_onVisit(aURI) { 1.110 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.111 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.112 + 1.113 + waitForOnDeleteVisits(function DHRAD_onDeleteVisits(aURI) { 1.114 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.115 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.116 + 1.117 + promiseClearHistory().then(run_next_test); 1.118 + }); 1.119 + gDownloadHistory.removeAllDownloads(); 1.120 + }); 1.121 + 1.122 + gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000); 1.123 + }); 1.124 +}); 1.125 + 1.126 +add_test(function test_dh_addBookmarkRemoveDownload() 1.127 +{ 1.128 + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, 1.129 + DOWNLOAD_URI, 1.130 + PlacesUtils.bookmarks.DEFAULT_INDEX, 1.131 + "A bookmark"); 1.132 + waitForOnVisit(function DHAD_onVisit(aURI) { 1.133 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.134 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.135 + 1.136 + waitForOnDeleteVisits(function DHRAD_onDeleteVisits(aURI) { 1.137 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.138 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.139 + 1.140 + promiseClearHistory().then(run_next_test); 1.141 + }); 1.142 + gDownloadHistory.removeAllDownloads(); 1.143 + }); 1.144 + 1.145 + gDownloadHistory.addDownload(DOWNLOAD_URI, null, Date.now() * 1000); 1.146 +}); 1.147 + 1.148 +add_test(function test_dh_addDownload_referrer() 1.149 +{ 1.150 + waitForOnVisit(function DHAD_prepareReferrer(aURI, aVisitID) { 1.151 + do_check_true(aURI.equals(REFERRER_URI)); 1.152 + let referrerVisitId = aVisitID; 1.153 + 1.154 + waitForOnVisit(function DHAD_onVisit(aURI, aVisitID, aTime, aSessionID, 1.155 + aReferringID) { 1.156 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.157 + do_check_eq(aReferringID, referrerVisitId); 1.158 + 1.159 + // Verify that the URI is already available in results at this time. 1.160 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.161 + 1.162 + promiseClearHistory().then(run_next_test); 1.163 + }); 1.164 + 1.165 + gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000); 1.166 + }); 1.167 + 1.168 + // Note that we don't pass the optional callback argument here because we must 1.169 + // ensure that we receive the onVisit notification before we call addDownload. 1.170 + PlacesUtils.asyncHistory.updatePlaces({ 1.171 + uri: REFERRER_URI, 1.172 + visits: [{ 1.173 + transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED, 1.174 + visitDate: Date.now() * 1000 1.175 + }] 1.176 + }); 1.177 +}); 1.178 + 1.179 +add_test(function test_dh_addDownload_disabledHistory() 1.180 +{ 1.181 + waitForOnVisit(function DHAD_onVisit(aURI) { 1.182 + // We should only receive the notification for the non-private URI. This 1.183 + // test is based on the assumption that visit notifications are received in 1.184 + // the same order of the addDownload calls, which is currently true because 1.185 + // database access is serialized on the same worker thread. 1.186 + do_check_true(aURI.equals(DOWNLOAD_URI)); 1.187 + 1.188 + do_check_true(!!page_in_database(DOWNLOAD_URI)); 1.189 + do_check_false(!!page_in_database(PRIVATE_URI)); 1.190 + 1.191 + promiseClearHistory().then(run_next_test); 1.192 + }); 1.193 + 1.194 + Services.prefs.setBoolPref("places.history.enabled", false); 1.195 + gDownloadHistory.addDownload(PRIVATE_URI, REFERRER_URI, Date.now() * 1000); 1.196 + 1.197 + // The addDownload functions calls CanAddURI synchronously, thus we can set 1.198 + // the preference back to true immediately (not all apps enable places by 1.199 + // default). 1.200 + Services.prefs.setBoolPref("places.history.enabled", true); 1.201 + gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000); 1.202 +}); 1.203 + 1.204 +/** 1.205 + * Tests that nsIDownloadHistory::AddDownload saves the additional download 1.206 + * details if the optional destination URL is specified. 1.207 + */ 1.208 +add_test(function test_dh_details() 1.209 +{ 1.210 + const REMOTE_URI = NetUtil.newURI("http://localhost/"); 1.211 + const SOURCE_URI = NetUtil.newURI("http://example.com/test_dh_details"); 1.212 + const DEST_FILE_NAME = "dest.txt"; 1.213 + 1.214 + // We must build a real, valid file URI for the destination. 1.215 + let destFileUri = NetUtil.newURI(FileUtils.getFile("TmpD", [DEST_FILE_NAME])); 1.216 + 1.217 + let titleSet = false; 1.218 + let destinationFileUriSet = false; 1.219 + let destinationFileNameSet = false; 1.220 + 1.221 + function checkFinished() 1.222 + { 1.223 + if (titleSet && destinationFileUriSet && destinationFileNameSet) { 1.224 + PlacesUtils.annotations.removeObserver(annoObserver); 1.225 + PlacesUtils.history.removeObserver(historyObserver); 1.226 + 1.227 + promiseClearHistory().then(run_next_test); 1.228 + } 1.229 + }; 1.230 + 1.231 + let annoObserver = { 1.232 + onPageAnnotationSet: function AO_onPageAnnotationSet(aPage, aName) 1.233 + { 1.234 + if (aPage.equals(SOURCE_URI)) { 1.235 + let value = PlacesUtils.annotations.getPageAnnotation(aPage, aName); 1.236 + switch (aName) 1.237 + { 1.238 + case "downloads/destinationFileURI": 1.239 + destinationFileUriSet = true; 1.240 + do_check_eq(value, destFileUri.spec); 1.241 + break; 1.242 + case "downloads/destinationFileName": 1.243 + destinationFileNameSet = true; 1.244 + do_check_eq(value, DEST_FILE_NAME); 1.245 + break; 1.246 + } 1.247 + checkFinished(); 1.248 + } 1.249 + }, 1.250 + onItemAnnotationSet: function() {}, 1.251 + onPageAnnotationRemoved: function() {}, 1.252 + onItemAnnotationRemoved: function() {} 1.253 + } 1.254 + 1.255 + let historyObserver = { 1.256 + onBeginUpdateBatch: function() {}, 1.257 + onEndUpdateBatch: function() {}, 1.258 + onVisit: function() {}, 1.259 + onTitleChanged: function HO_onTitleChanged(aURI, aPageTitle) 1.260 + { 1.261 + if (aURI.equals(SOURCE_URI)) { 1.262 + titleSet = true; 1.263 + do_check_eq(aPageTitle, DEST_FILE_NAME); 1.264 + checkFinished(); 1.265 + } 1.266 + }, 1.267 + onDeleteURI: function() {}, 1.268 + onClearHistory: function() {}, 1.269 + onPageChanged: function() {}, 1.270 + onDeleteVisits: function() {} 1.271 + }; 1.272 + 1.273 + PlacesUtils.annotations.addObserver(annoObserver, false); 1.274 + PlacesUtils.history.addObserver(historyObserver, false); 1.275 + 1.276 + // Both null values and remote URIs should not cause errors. 1.277 + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000); 1.278 + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, null); 1.279 + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, REMOTE_URI); 1.280 + 1.281 + // Valid local file URIs should cause the download details to be saved. 1.282 + gDownloadHistory.addDownload(SOURCE_URI, null, Date.now() * 1000, 1.283 + destFileUri); 1.284 +});