michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * Tests that requesting clear history at shutdown will really clear history. michael@0: */ michael@0: michael@0: const URIS = [ michael@0: "http://a.example1.com/" michael@0: , "http://b.example1.com/" michael@0: , "http://b.example2.com/" michael@0: , "http://c.example3.com/" michael@0: ]; michael@0: michael@0: const TOPIC_CONNECTION_CLOSED = "places-connection-closed"; michael@0: michael@0: let EXPECTED_NOTIFICATIONS = [ michael@0: "places-shutdown" michael@0: , "places-will-close-connection" michael@0: , "places-expiration-finished" michael@0: , "places-connection-closed" michael@0: ]; michael@0: michael@0: const UNEXPECTED_NOTIFICATIONS = [ michael@0: "xpcom-shutdown" michael@0: ]; michael@0: michael@0: const URL = "ftp://localhost/clearHistoryOnShutdown/"; michael@0: michael@0: // Send the profile-after-change notification to the form history component to ensure michael@0: // that it has been initialized. michael@0: var formHistoryStartup = Cc["@mozilla.org/satchel/form-history-startup;1"]. michael@0: getService(Ci.nsIObserver); michael@0: formHistoryStartup.observe(null, "profile-after-change", null); michael@0: michael@0: let notificationIndex = 0; michael@0: michael@0: let notificationsObserver = { michael@0: observe: function observe(aSubject, aTopic, aData) { michael@0: print("Received notification: " + aTopic); michael@0: michael@0: // Note that some of these notifications could arrive multiple times, for michael@0: // example in case of sync, we allow that. michael@0: if (EXPECTED_NOTIFICATIONS[notificationIndex] != aTopic) michael@0: notificationIndex++; michael@0: do_check_eq(EXPECTED_NOTIFICATIONS[notificationIndex], aTopic); michael@0: michael@0: if (aTopic != TOPIC_CONNECTION_CLOSED) michael@0: return; michael@0: michael@0: getDistinctNotifications().forEach( michael@0: function (topic) Services.obs.removeObserver(notificationsObserver, topic) michael@0: ); michael@0: michael@0: print("Looking for uncleared stuff."); michael@0: michael@0: let stmt = DBConn().createStatement( michael@0: "SELECT id FROM moz_places WHERE url = :page_url " michael@0: ); michael@0: michael@0: try { michael@0: URIS.forEach(function(aUrl) { michael@0: stmt.params.page_url = aUrl; michael@0: do_check_false(stmt.executeStep()); michael@0: stmt.reset(); michael@0: }); michael@0: } finally { michael@0: stmt.finalize(); michael@0: } michael@0: michael@0: // Check cache. michael@0: checkCache(URL); michael@0: } michael@0: } michael@0: michael@0: let timeInMicroseconds = Date.now() * 1000; michael@0: michael@0: function run_test() { michael@0: run_next_test(); michael@0: } michael@0: michael@0: add_task(function test_execute() { michael@0: do_test_pending(); michael@0: michael@0: print("Initialize browserglue before Places"); michael@0: michael@0: // Avoid default bookmarks import. michael@0: let glue = Cc["@mozilla.org/browser/browserglue;1"]. michael@0: getService(Ci.nsIObserver); michael@0: glue.observe(null, "initial-migration-will-import-default-bookmarks", null); michael@0: michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.cache", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.cookies", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.offlineApps", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.history", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.downloads", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.cookies", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.formData", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.passwords", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.sessions", true); michael@0: Services.prefs.setBoolPref("privacy.clearOnShutdown.siteSettings", true); michael@0: michael@0: Services.prefs.setBoolPref("privacy.sanitize.sanitizeOnShutdown", true); michael@0: michael@0: print("Add visits."); michael@0: for (let aUrl of URIS) { michael@0: yield promiseAddVisits({uri: uri(aUrl), visitDate: timeInMicroseconds++, michael@0: transition: PlacesUtils.history.TRANSITION_TYPED}) michael@0: } michael@0: print("Add cache."); michael@0: storeCache(URL, "testData"); michael@0: }); michael@0: michael@0: function run_test_continue() michael@0: { michael@0: print("Simulate and wait shutdown."); michael@0: getDistinctNotifications().forEach( michael@0: function (topic) michael@0: Services.obs.addObserver(notificationsObserver, topic, false) michael@0: ); michael@0: michael@0: shutdownPlaces(); michael@0: michael@0: // Shutdown the download manager. michael@0: Services.obs.notifyObservers(null, "quit-application", null); michael@0: } michael@0: michael@0: function getDistinctNotifications() { michael@0: let ar = EXPECTED_NOTIFICATIONS.concat(UNEXPECTED_NOTIFICATIONS); michael@0: return [ar[i] for (i in ar) if (ar.slice(0, i).indexOf(ar[i]) == -1)]; michael@0: } michael@0: michael@0: function storeCache(aURL, aContent) { michael@0: let cache = Services.cache2; michael@0: let storage = cache.diskCacheStorage(LoadContextInfo.default, false); michael@0: michael@0: var storeCacheListener = { michael@0: onCacheEntryCheck: function (entry, appcache) { michael@0: return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; michael@0: }, michael@0: michael@0: onCacheEntryAvailable: function (entry, isnew, appcache, status) { michael@0: do_check_eq(status, Cr.NS_OK); michael@0: michael@0: entry.setMetaDataElement("servertype", "0"); michael@0: var os = entry.openOutputStream(0); michael@0: michael@0: var written = os.write(aContent, aContent.length); michael@0: if (written != aContent.length) { michael@0: do_throw("os.write has not written all data!\n" + michael@0: " Expected: " + written + "\n" + michael@0: " Actual: " + aContent.length + "\n"); michael@0: } michael@0: os.close(); michael@0: entry.close(); michael@0: do_execute_soon(run_test_continue); michael@0: } michael@0: }; michael@0: michael@0: storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "", michael@0: Ci.nsICacheStorage.OPEN_NORMALLY, michael@0: storeCacheListener); michael@0: } michael@0: michael@0: michael@0: function checkCache(aURL) { michael@0: let cache = Services.cache2; michael@0: let storage = cache.diskCacheStorage(LoadContextInfo.default, false); michael@0: michael@0: var checkCacheListener = { michael@0: onCacheEntryAvailable: function (entry, isnew, appcache, status) { michael@0: do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND); michael@0: do_test_finished(); michael@0: } michael@0: }; michael@0: michael@0: storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "", michael@0: Ci.nsICacheStorage.OPEN_READONLY, michael@0: checkCacheListener); michael@0: }