diff options
Diffstat (limited to 'comm/suite/modules/test/unit')
-rw-r--r-- | comm/suite/modules/test/unit/head.js | 135 | ||||
-rw-r--r-- | comm/suite/modules/test/unit/test_browser_sanitizer.js | 339 | ||||
-rw-r--r-- | comm/suite/modules/test/unit/xpcshell.ini | 6 |
3 files changed, 480 insertions, 0 deletions
diff --git a/comm/suite/modules/test/unit/head.js b/comm/suite/modules/test/unit/head.js new file mode 100644 index 0000000000..c947a4533c --- /dev/null +++ b/comm/suite/modules/test/unit/head.js @@ -0,0 +1,135 @@ +var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +ChromeUtils.defineModuleGetter(this, "PlacesUtils", + "resource://gre/modules/PlacesUtils.jsm"); +ChromeUtils.defineModuleGetter(this, "Promise", + "resource://gre/modules/commonjs/sdk/core/promise.js"); + +// Need to explicitly load profile for Places +do_get_profile(); + +/** + * Waits until a new cache entry has been opened + * + * @return {Promise} + * @resolves When the new cache entry has been opened. + * @rejects Never. + * + */ +function promiseOpenCacheEntry(aKey, aAccessMode, aCacheSession) +{ + let deferred = Promise.defer(); + + let cacheListener = { + onCacheEntryAvailable: function (entry, access, status) { + deferred.resolve(entry); + }, + + onCacheEntryDoomed: function (status) { + } + }; + + aCacheSession.asyncOpenCacheEntry(aKey, aAccessMode, cacheListener); + + return deferred.promise; +} + +/** + * Waits for all pending async statements on the default connection. + * + * @return {Promise} + * @resolves When all pending async statements finished. + * @rejects Never. + * + * @note The result is achieved by asynchronously executing a query requiring + * a write lock. Since all statements on the same connection are + * serialized, the end of this write operation means that all writes are + * complete. Note that WAL makes so that writers don't block readers, but + * this is a problem only across different connections. + */ +function promiseAsyncUpdates() +{ + let deferred = Promise.defer(); + + let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) + .DBConnection; + let begin = db.createAsyncStatement("BEGIN EXCLUSIVE"); + begin.executeAsync(); + begin.finalize(); + + let commit = db.createAsyncStatement("COMMIT"); + commit.executeAsync({ + handleResult: function() {}, + handleError: function() {}, + handleCompletion: function(aReason) + { + deferred.resolve(); + } + }); + commit.finalize(); + + return deferred.promise; +} + +/** + * Asynchronously adds visits to a page. + * + * @param aPlaceInfo + * Can be an nsIURI, in such a case a single LINK visit will be added. + * Otherwise can be an object describing the visit to add, or an array + * of these objects: + * { uri: nsIURI of the page, + * transition: one of the TRANSITION_* from nsINavHistoryService, + * [optional] title: title of the page, + * [optional] visitDate: visit date in microseconds from the epoch + * [optional] referrer: nsIURI of the referrer for this visit + * } + * + * @return {Promise} + * @resolves When all visits have been added successfully. + * @rejects JavaScript exception. + */ +function promiseAddVisits(aPlaceInfo) +{ + let deferred = Promise.defer(); + let places = []; + if (aPlaceInfo instanceof Ci.nsIURI) { + places.push({ uri: aPlaceInfo }); + } + else if (Array.isArray(aPlaceInfo)) { + places = places.concat(aPlaceInfo); + } else { + places.push(aPlaceInfo) + } + + // Create mozIVisitInfo for each entry. + let now = Date.now(); + for (let i = 0; i < places.length; i++) { + if (!places[i].title) { + places[i].title = "test visit for " + places[i].uri.spec; + } + places[i].visits = [{ + transitionType: places[i].transition === undefined ? PlacesUtils.history.TRANSITION_LINK + : places[i].transition, + visitDate: places[i].visitDate || (now++) * 1000, + referrerURI: places[i].referrer + }]; + } + + PlacesUtils.asyncHistory.updatePlaces( + places, + { + handleError: function AAV_handleError(aResultCode, aPlaceInfo) { + let ex = new Components.Exception("Unexpected error in adding visits.", + aResultCode); + deferred.reject(ex); + }, + handleResult: function () {}, + handleCompletion: function UP_handleCompletion() { + deferred.resolve(); + } + } + ); + + return deferred.promise; +} diff --git a/comm/suite/modules/test/unit/test_browser_sanitizer.js b/comm/suite/modules/test/unit/test_browser_sanitizer.js new file mode 100644 index 0000000000..9e6ad39d08 --- /dev/null +++ b/comm/suite/modules/test/unit/test_browser_sanitizer.js @@ -0,0 +1,339 @@ +ChromeUtils.import("resource:///modules/Sanitizer.jsm", this); +ChromeUtils.defineModuleGetter(this, "FormHistory", + "resource://gre/modules/FormHistory.jsm"); + +var sanTests = { + cache: { + desc: "Cache", + async setup() { + var entry = null; + this.cs = Services.cache.createSession("SanitizerTest", Ci.nsICache.STORE_ANYWHERE, true); + entry = await promiseOpenCacheEntry("http://santizer.test", Ci.nsICache.ACCESS_READ_WRITE, this.cs); + entry.setMetaDataElement("Foo", "Bar"); + entry.markValid(); + entry.close(); + }, + + async check(aShouldBeCleared) { + let entry = null; + entry = await promiseOpenCacheEntry("http://santizer.test", Ci.nsICache.ACCESS_READ, this.cs); + + if (entry) { + entry.close(); + } + + Assert.equal(!entry, aShouldBeCleared); + } + }, + + offlineApps: { + desc: "Offline app cache", + async setup() { + //XXX test offline DOMStorage + var entry = null; + this.cs = Services.cache.createSession("SanitizerTest", Ci.nsICache.STORE_OFFLINE, true); + entry = await promiseOpenCacheEntry("http://santizer.test", Ci.nsICache.ACCESS_READ_WRITE, this.cs); + entry.setMetaDataElement("Foo", "Bar"); + entry.markValid(); + entry.close(); + }, + + async check(aShouldBeCleared) { + var entry = null; + entry = await promiseOpenCacheEntry("http://santizer.test", Ci.nsICache.ACCESS_READ, this.cs); + if (entry) { + entry.close(); + } + + Assert.equal(!entry, aShouldBeCleared); + } + }, + + cookies: { + desc: "Cookie", + setup: function() { + Services.prefs.setIntPref("network.cookie.cookieBehavior", 0); + this.uri = Services.io.newURI("http://sanitizer.test/"); + this.cs = Cc["@mozilla.org/cookieService;1"] + .getService(Ci.nsICookieService); + this.cs.setCookieString(this.uri, null, "Sanitizer!", null); + }, + + check: function(aShouldBeCleared) { + if (aShouldBeCleared) + Assert.notEqual(this.cs.getCookieString(this.uri, null), "Sanitizer!"); + else + Assert.equal(this.cs.getCookieString(this.uri, null), "Sanitizer!"); + } + }, + + history: { + desc: "History", + async setup() { + var uri = Services.io.newURI("http://sanitizer.test/"); + await promiseAddVisits({ + uri: uri, + title: "Sanitizer!" + }); + }, + + check: function(aShouldBeCleared) { + var rv = false; + var history = Cc["@mozilla.org/browser/nav-history-service;1"] + .getService(Ci.nsINavHistoryService); + var options = history.getNewQueryOptions(); + var query = history.getNewQuery(); + query.searchTerms = "Sanitizer!"; + var results = history.executeQuery(query, options).root; + results.containerOpen = true; + for (var i = 0; i < results.childCount; i++) { + if (results.getChild(i).uri == "http://sanitizer.test/") { + rv = true; + break; + } + } + + // Close container after reading from it + results.containerOpen = false; + + Assert.equal(rv, !aShouldBeCleared); + } + }, + + urlbar: { + desc: "Location bar history", + setup: function() { + // Create urlbarhistory file first otherwise tests will fail. + var file = Services.dirsvc.get("ProfD", Ci.nsIFile); + file.append("urlbarhistory.sqlite"); + if (!file.exists()) { + var connection = Cc["@mozilla.org/storage/service;1"] + .getService(Ci.mozIStorageService) + .openDatabase(file); + connection.createTable("urlbarhistory", "url TEXT"); + connection.executeSimpleSQL( + "INSERT INTO urlbarhistory (url) VALUES ('Sanitizer')"); + connection.close(); + } + + // Open location dialog. + Services.prefs.setStringPref("general.open_location.last_url", "Sanitizer!"); + }, + + check: function(aShouldBeCleared) { + let locData; + try { + locData = Services.prefs.getStringPref("general.open_location.last_url"); + } catch(ex) {} + + Assert.equal(locData == "Sanitizer!", !aShouldBeCleared); + + var file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("ProfD", Ci.nsIFile); + file.append("urlbarhistory.sqlite"); + + var connection = Cc["@mozilla.org/storage/service;1"] + .getService(Ci.mozIStorageService) + .openDatabase(file); + var urlbar = connection.tableExists("urlbarhistory"); + if (urlbar) { + var handle = connection.createStatement( + "SELECT url FROM urlbarhistory"); + if (handle.executeStep()) + urlbar = (handle.getString(0) == "Sanitizer"); + handle.reset(); + handle.finalize(); + } + connection.close(); + + Assert.equal(urlbar, !aShouldBeCleared); + } + }, + + formdata: { + desc: "Form history", + async setup() { + // Adds a form entry to history. + function promiseAddFormEntry(aName, aValue) { + return new Promise((resolve, reject) => + FormHistory.update({ op: "add", fieldname: aName, value: aValue }, + { handleError(error) { + reject(); + throw new Error("Error occurred updating form history: " + error); + }, + handleCompletion(reason) { + resolve(); + } + }) + ) + } + await promiseAddFormEntry("Sanitizer", "Foo"); + }, + async check(aShouldBeCleared) { + // Check if a form name exists. + function formNameExists(aName) { + return new Promise((resolve, reject) => { + let count = 0; + FormHistory.count({ fieldname: aName }, + { handleResult: result => count = result, + handleError(error) { + reject(error); + throw new Error("Error occurred searching form history: " + error); + }, + handleCompletion(reason) { + if (!reason) { + resolve(count); + } + } + }); + }); + } + + // Checking for Sanitizer form history entry creation. + let exists = await formNameExists("Sanitizer"); + Assert.equal(exists, !aShouldBeCleared); + } + }, + + downloads: { + desc: "Download", + setup: function() { + var uri = Services.io.newURI("http://sanitizer.test/"); + var file = Services.dirsvc.get("TmpD", Ci.nsIFile); + file.append("sanitizer.file"); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0666", 8)); + var dest = Services.io.newFileURI(file); + + this.dm = Cc["@mozilla.org/download-manager;1"] + .getService(Ci.nsIDownloadManager); + + const nsIWBP = Ci.nsIWebBrowserPersist; + var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] + .createInstance(nsIWBP); + persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES | + nsIWBP.PERSIST_FLAGS_BYPASS_CACHE | + nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; + + this.dl = this.dm.addDownload(this.dm.DOWNLOAD_CANCELED, uri, dest, + "Sanitizer!", null, + Math.round(Date.now() * 1000), null, + persist, false); + + // Stupid DM... + this.dm.cancelDownload(this.dl.id); + }, + + check: function(aShouldBeCleared) { + var dl = null; + try { + dl = this.dm.getDownload(this.dl.id); + } catch(ex) {} + + if (aShouldBeCleared) + Assert.equal(!dl, aShouldBeCleared) + else + Assert.equal(dl.displayName, "Sanitizer!"); + } + }, + + passwords: { + desc: "Login manager", + setup: function() { + this.pm = Cc["@mozilla.org/login-manager;1"] + .getService(Ci.nsILoginManager); + var info = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", + Ci.nsILoginInfo, "init"); + var login = new info("http://sanitizer.test", null, "Rick Astley Fan Club", + "dolske", "iliketurtles1", "", ""); + this.pm.addLogin(login); + }, + + check: function(aShouldBeCleared) { + let rv = false; + let logins = this.pm.findLogins({}, "http://sanitizer.test", null, "Rick Astley Fan Club"); + for (var i = 0; i < logins.length; i++) { + if (logins[i].username == "dolske") { + rv = true; + break; + } + } + + Assert.equal(rv, !aShouldBeCleared); + } + }, + + sessions: { + desc: "HTTP auth session", + setup: function() { + this.authMgr = Cc["@mozilla.org/network/http-auth-manager;1"] + .getService(Ci.nsIHttpAuthManager); + + this.authMgr.setAuthIdentity("http", "sanitizer.test", 80, "basic", "Sanitizer", + "", "Foo", "fooo", "foo12"); + }, + + check: function(aShouldBeCleared) { + var domain = {}; + var user = {}; + var password = {}; + + try { + this.authMgr.getAuthIdentity("http", "sanitizer.test", 80, "basic", "Sanitizer", + "", domain, user, password); + } catch(ex) {} + + Assert.equal(domain.value == "Foo", !aShouldBeCleared); + } + } +} + +async function fullSanitize() { + info("Now doing a full sanitize run"); + var prefs = Services.prefs.getBranch("privacy.clearOnShutdown."); + + Services.prefs.setBoolPref("privacy.sanitize.promptOnSanitize", false); + + for (var testName in sanTests) { + var test = sanTests[testName]; + await test.setup(); + prefs.setBoolPref(testName, true); + } + + Sanitizer.sanitize(); + + for (var testName in sanTests) { + var test = sanTests[testName]; + await test.check(true); + info(test.desc + " data cleared by full sanitize"); + try { + prefs.clearUserPref(testName); + } catch (ex) {} + } + + try { + Services.prefs.clearUserPref("privacy.sanitize.promptOnSanitize"); + } catch(ex) {} +} + +function run_test() +{ + run_next_test(); +} + +add_task(async function test_browser_sanitizer() +{ + for (var testName in sanTests) { + let test = sanTests[testName]; + dump("\nExecuting test: " + testName + "\n" + "*** " + test.desc + "\n"); + await test.setup(); + await test.check(false); + + Sanitizer.items[testName].clear(); + info(test.desc + " data cleared"); + + await test.check(true); + } +}); + +add_task(fullSanitize); diff --git a/comm/suite/modules/test/unit/xpcshell.ini b/comm/suite/modules/test/unit/xpcshell.ini new file mode 100644 index 0000000000..4f6c1dad63 --- /dev/null +++ b/comm/suite/modules/test/unit/xpcshell.ini @@ -0,0 +1,6 @@ +[DEFAULT] +head = head.js +tail = +run-sequentially = Avoid bustage. + +[test_browser_sanitizer.js] |