From eb70e6e3d0bff11c25f14b1196025791bf2308fb Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Tue, 25 Feb 2020 15:07:00 -0500 Subject: Issue #439 - Remove tests from toolkit/ --- .../components/passwordmgr/test/unit/.eslintrc.js | 7 - .../passwordmgr/test/unit/data/corruptDB.sqlite | Bin 32772 -> 0 bytes .../components/passwordmgr/test/unit/data/key3.db | Bin 16384 -> 0 bytes .../passwordmgr/test/unit/data/signons-v1.sqlite | Bin 8192 -> 0 bytes .../passwordmgr/test/unit/data/signons-v1v2.sqlite | Bin 10240 -> 0 bytes .../passwordmgr/test/unit/data/signons-v2.sqlite | Bin 11264 -> 0 bytes .../passwordmgr/test/unit/data/signons-v2v3.sqlite | Bin 12288 -> 0 bytes .../passwordmgr/test/unit/data/signons-v3.sqlite | Bin 11264 -> 0 bytes .../passwordmgr/test/unit/data/signons-v3v4.sqlite | Bin 11264 -> 0 bytes .../passwordmgr/test/unit/data/signons-v4.sqlite | Bin 294912 -> 0 bytes .../passwordmgr/test/unit/data/signons-v4v5.sqlite | Bin 327680 -> 0 bytes .../passwordmgr/test/unit/data/signons-v5v6.sqlite | Bin 327680 -> 0 bytes .../test/unit/data/signons-v999-2.sqlite | Bin 8192 -> 0 bytes .../passwordmgr/test/unit/data/signons-v999.sqlite | Bin 11264 -> 0 bytes toolkit/components/passwordmgr/test/unit/head.js | 135 ------ .../passwordmgr/test/unit/test_OSCrypto_win.js | 75 --- .../passwordmgr/test/unit/test_context_menu.js | 165 ------- .../passwordmgr/test/unit/test_dedupeLogins.js | 284 ------------ .../passwordmgr/test/unit/test_disabled_hosts.js | 196 -------- .../passwordmgr/test/unit/test_getFormFields.js | 147 ------ .../test/unit/test_getPasswordFields.js | 156 ------- .../test/unit/test_getPasswordOrigin.js | 28 -- .../passwordmgr/test/unit/test_isOriginMatching.js | 40 -- .../test/unit/test_legacy_empty_formSubmitURL.js | 107 ----- .../test/unit/test_legacy_validation.js | 76 --- .../passwordmgr/test/unit/test_logins_change.js | 384 ---------------- .../test/unit/test_logins_decrypt_failure.js | 77 ---- .../passwordmgr/test/unit/test_logins_metainfo.js | 284 ------------ .../passwordmgr/test/unit/test_logins_search.js | 220 --------- .../passwordmgr/test/unit/test_maybeImportLogin.js | 169 ------- .../test/unit/test_module_LoginImport.js | 243 ---------- .../test/unit/test_module_LoginStore.js | 206 --------- .../passwordmgr/test/unit/test_notifications.js | 172 ------- .../passwordmgr/test/unit/test_recipes_add.js | 177 ------- .../passwordmgr/test/unit/test_recipes_content.js | 39 -- .../test/unit/test_removeLegacySignonFiles.js | 69 --- .../test/unit/test_search_schemeUpgrades.js | 184 -------- .../passwordmgr/test/unit/test_storage.js | 102 ----- .../test/unit/test_storage_mozStorage.js | 507 --------------------- .../passwordmgr/test/unit/test_telemetry.js | 187 -------- .../test/unit/test_user_autocomplete_result.js | 488 -------------------- .../components/passwordmgr/test/unit/xpcshell.ini | 46 -- 42 files changed, 4970 deletions(-) delete mode 100644 toolkit/components/passwordmgr/test/unit/.eslintrc.js delete mode 100644 toolkit/components/passwordmgr/test/unit/data/corruptDB.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/key3.db delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v1.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v1v2.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v2.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v2v3.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v3.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v3v4.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v4.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v4v5.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v5v6.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v999-2.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/data/signons-v999.sqlite delete mode 100644 toolkit/components/passwordmgr/test/unit/head.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_OSCrypto_win.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_context_menu.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_dedupeLogins.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_disabled_hosts.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_getFormFields.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_getPasswordFields.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_isOriginMatching.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_legacy_empty_formSubmitURL.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_legacy_validation.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_logins_change.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_logins_decrypt_failure.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_logins_metainfo.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_logins_search.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_maybeImportLogin.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_module_LoginImport.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_module_LoginStore.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_notifications.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_recipes_add.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_recipes_content.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_removeLegacySignonFiles.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_search_schemeUpgrades.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_storage.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_telemetry.js delete mode 100644 toolkit/components/passwordmgr/test/unit/test_user_autocomplete_result.js delete mode 100644 toolkit/components/passwordmgr/test/unit/xpcshell.ini (limited to 'toolkit/components/passwordmgr/test/unit') diff --git a/toolkit/components/passwordmgr/test/unit/.eslintrc.js b/toolkit/components/passwordmgr/test/unit/.eslintrc.js deleted file mode 100644 index d35787cd2..000000000 --- a/toolkit/components/passwordmgr/test/unit/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { - "extends": [ - "../../../../../testing/xpcshell/xpcshell.eslintrc.js" - ] -}; diff --git a/toolkit/components/passwordmgr/test/unit/data/corruptDB.sqlite b/toolkit/components/passwordmgr/test/unit/data/corruptDB.sqlite deleted file mode 100644 index b234246ca..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/corruptDB.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/key3.db b/toolkit/components/passwordmgr/test/unit/data/key3.db deleted file mode 100644 index a83a0a577..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/key3.db and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v1.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v1.sqlite deleted file mode 100644 index fe030b61f..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v1.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v1v2.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v1v2.sqlite deleted file mode 100644 index 729512a12..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v1v2.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v2.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v2.sqlite deleted file mode 100644 index a6c72b31e..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v2.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v2v3.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v2v3.sqlite deleted file mode 100644 index 359df5d31..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v2v3.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v3.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v3.sqlite deleted file mode 100644 index 918f4142f..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v3.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v3v4.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v3v4.sqlite deleted file mode 100644 index e06c33aae..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v3v4.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v4.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v4.sqlite deleted file mode 100644 index 227c09c81..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v4.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v4v5.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v4v5.sqlite deleted file mode 100644 index 4534cf255..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v4v5.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v5v6.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v5v6.sqlite deleted file mode 100644 index eb4ee6d01..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v5v6.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v999-2.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v999-2.sqlite deleted file mode 100644 index e09c4f710..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v999-2.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/data/signons-v999.sqlite b/toolkit/components/passwordmgr/test/unit/data/signons-v999.sqlite deleted file mode 100644 index 0328a1a02..000000000 Binary files a/toolkit/components/passwordmgr/test/unit/data/signons-v999.sqlite and /dev/null differ diff --git a/toolkit/components/passwordmgr/test/unit/head.js b/toolkit/components/passwordmgr/test/unit/head.js deleted file mode 100644 index baf958ab4..000000000 --- a/toolkit/components/passwordmgr/test/unit/head.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Provides infrastructure for automated login components tests. - */ - -"use strict"; - -// Globals - -let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/LoginRecipes.jsm"); -Cu.import("resource://gre/modules/LoginHelper.jsm"); -Cu.import("resource://testing-common/MockDocument.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "DownloadPaths", - "resource://gre/modules/DownloadPaths.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); - -const LoginInfo = - Components.Constructor("@mozilla.org/login-manager/loginInfo;1", - "nsILoginInfo", "init"); - -// Import LoginTestUtils.jsm as LoginTestUtils. -XPCOMUtils.defineLazyModuleGetter(this, "LoginTestUtils", - "resource://testing-common/LoginTestUtils.jsm"); -LoginTestUtils.Assert = Assert; -const TestData = LoginTestUtils.testData; -const newPropertyBag = LoginHelper.newPropertyBag; - -/** - * All the tests are implemented with add_task, this starts them automatically. - */ -function run_test() -{ - do_get_profile(); - run_next_test(); -} - -// Global helpers - -// Some of these functions are already implemented in other parts of the source -// tree, see bug 946708 about sharing more code. - -// While the previous test file should have deleted all the temporary files it -// used, on Windows these might still be pending deletion on the physical file -// system. Thus, start from a new base number every time, to make a collision -// with a file that is still pending deletion highly unlikely. -let gFileCounter = Math.floor(Math.random() * 1000000); - -/** - * Returns a reference to a temporary file, that is guaranteed not to exist, and - * to have never been created before. - * - * @param aLeafName - * Suggested leaf name for the file to be created. - * - * @return nsIFile pointing to a non-existent file in a temporary directory. - * - * @note It is not enough to delete the file if it exists, or to delete the file - * after calling nsIFile.createUnique, because on Windows the delete - * operation in the file system may still be pending, preventing a new - * file with the same name to be created. - */ -function getTempFile(aLeafName) -{ - // Prepend a serial number to the extension in the suggested leaf name. - let [base, ext] = DownloadPaths.splitBaseNameAndExtension(aLeafName); - let leafName = base + "-" + gFileCounter + ext; - gFileCounter++; - - // Get a file reference under the temporary directory for this test file. - let file = FileUtils.getFile("TmpD", [leafName]); - do_check_false(file.exists()); - - do_register_cleanup(function () { - if (file.exists()) { - file.remove(false); - } - }); - - return file; -} - -const RecipeHelpers = { - initNewParent() { - return (new LoginRecipesParent({ defaults: null })).initializationPromise; - }, -}; - -// Initialization functions common to all tests - -add_task(function* test_common_initialize() -{ - // Before initializing the service for the first time, we should copy the key - // file required to decrypt the logins contained in the SQLite databases used - // by migration tests. This file is not required for the other tests. - yield OS.File.copy(do_get_file("data/key3.db").path, - OS.Path.join(OS.Constants.Path.profileDir, "key3.db")); - - // Ensure that the service and the storage module are initialized. - yield Services.logins.initializationPromise; - - // Ensure that every test file starts with an empty database. - LoginTestUtils.clearData(); - - // Clean up after every test. - do_register_cleanup(() => LoginTestUtils.clearData()); -}); - -/** - * Compare two FormLike to see if they represent the same information. Elements - * are compared using their @id attribute. - */ -function formLikeEqual(a, b) { - Assert.strictEqual(Object.keys(a).length, Object.keys(b).length, - "Check the formLikes have the same number of properties"); - - for (let propName of Object.keys(a)) { - if (propName == "elements") { - Assert.strictEqual(a.elements.length, b.elements.length, "Check element count"); - for (let i = 0; i < a.elements.length; i++) { - Assert.strictEqual(a.elements[i].id, b.elements[i].id, "Check element " + i + " id"); - } - continue; - } - Assert.strictEqual(a[propName], b[propName], "Compare formLike " + propName + " property"); - } -} diff --git a/toolkit/components/passwordmgr/test/unit/test_OSCrypto_win.js b/toolkit/components/passwordmgr/test/unit/test_OSCrypto_win.js deleted file mode 100644 index 94d2e50c0..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_OSCrypto_win.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Tests the OSCrypto object. - */ - -"use strict"; - -// Globals - -XPCOMUtils.defineLazyModuleGetter(this, "OSCrypto", - "resource://gre/modules/OSCrypto.jsm"); - -var crypto = new OSCrypto(); - -// Tests - -add_task(function test_getIELoginHash() -{ - do_check_eq(crypto.getIELoginHash("https://bugzilla.mozilla.org/page.cgi"), - "4A66FE96607885790F8E67B56EEE52AB539BAFB47D"); - - do_check_eq(crypto.getIELoginHash("https://github.com/login"), - "0112F7DCE67B8579EA01367678AA44AB9868B5A143"); - - do_check_eq(crypto.getIELoginHash("https://login.live.com/login.srf"), - "FBF92E5D804C82717A57856533B779676D92903688"); - - do_check_eq(crypto.getIELoginHash("https://preview.c9.io/riadh/w1/pass.1.html"), - "6935CF27628830605927F86AB53831016FC8973D1A"); - - - do_check_eq(crypto.getIELoginHash("https://reviewboard.mozilla.org/account/login/"), - "09141FD287E2E59A8B1D3BB5671537FD3D6B61337A"); - - do_check_eq(crypto.getIELoginHash("https://www.facebook.com/"), - "EF44D3E034009CB0FD1B1D81A1FF3F3335213BD796"); - -}); - -add_task(function test_decryptData_encryptData() -{ - function decryptEncryptTest(key) { - do_check_eq(crypto.decryptData(crypto.encryptData("", key), key), - ""); - - do_check_eq(crypto.decryptData(crypto.encryptData("secret", key), key), - "secret"); - - do_check_eq(crypto.decryptData(crypto.encryptData("https://www.mozilla.org", key), - key), - "https://www.mozilla.org"); - - do_check_eq(crypto.decryptData(crypto.encryptData("https://reviewboard.mozilla.org", key), - key), - "https://reviewboard.mozilla.org"); - - do_check_eq(crypto.decryptData(crypto.encryptData("https://bugzilla.mozilla.org/page.cgi", - key), - key), - "https://bugzilla.mozilla.org/page.cgi"); - } - - let keys = [null, "a", "keys", "abcdedf", "pass", "https://bugzilla.mozilla.org/page.cgi", - "https://login.live.com/login.srf"]; - for (let key of keys) { - decryptEncryptTest(key); - } - let url = "https://twitter.com/"; - let value = [1, 0, 0, 0, 208, 140, 157, 223, 1, 21, 209, 17, 140, 122, 0, 192, 79, 194, 151, 235, 1, 0, 0, 0, 254, 58, 230, 75, 132, 228, 181, 79, 184, 160, 37, 106, 201, 29, 42, 152, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 16, 102, 0, 0, 0, 1, 0, 0, 32, 0, 0, 0, 90, 136, 17, 124, 122, 57, 178, 24, 34, 86, 209, 198, 184, 107, 58, 58, 32, 98, 61, 239, 129, 101, 56, 239, 114, 159, 139, 165, 183, 40, 183, 85, 0, 0, 0, 0, 14, 128, 0, 0, 0, 2, 0, 0, 32, 0, 0, 0, 147, 170, 34, 21, 53, 227, 191, 6, 201, 84, 106, 31, 57, 227, 46, 127, 219, 199, 80, 142, 37, 104, 112, 223, 26, 165, 223, 55, 176, 89, 55, 37, 112, 0, 0, 0, 98, 70, 221, 109, 5, 152, 46, 11, 190, 213, 226, 58, 244, 20, 180, 217, 63, 155, 227, 132, 7, 151, 235, 6, 37, 232, 176, 182, 141, 191, 251, 50, 20, 123, 53, 11, 247, 233, 112, 121, 130, 27, 168, 68, 92, 144, 192, 7, 12, 239, 53, 217, 253, 155, 54, 109, 236, 216, 225, 245, 79, 234, 165, 225, 104, 36, 77, 13, 195, 237, 143, 165, 100, 107, 230, 70, 54, 19, 179, 35, 8, 101, 93, 202, 121, 210, 222, 28, 93, 122, 36, 84, 185, 249, 238, 3, 102, 149, 248, 94, 137, 16, 192, 22, 251, 220, 22, 223, 16, 58, 104, 187, 64, 0, 0, 0, 70, 72, 15, 119, 144, 66, 117, 203, 190, 82, 131, 46, 111, 130, 238, 191, 170, 63, 186, 117, 46, 88, 171, 3, 94, 146, 75, 86, 243, 159, 63, 195, 149, 25, 105, 141, 42, 217, 108, 18, 63, 62, 98, 182, 241, 195, 12, 216, 152, 230, 176, 253, 202, 129, 41, 185, 135, 111, 226, 92, 27, 78, 27, 198]; - - let arr1 = crypto.arrayToString(value); - let arr2 = crypto.stringToArray(crypto.decryptData(crypto.encryptData(arr1, url), url)); - for (let i = 0; i < arr1.length; i++) { - do_check_eq(arr2[i], value[i]); - } -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_context_menu.js b/toolkit/components/passwordmgr/test/unit/test_context_menu.js deleted file mode 100644 index 722c13e15..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_context_menu.js +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Test the password manager context menu. - */ - -"use strict"; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/LoginManagerContextMenu.jsm"); - -XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() { - return Services.strings. - createBundle("chrome://passwordmgr/locale/passwordmgr.properties"); -}); - -/** - * Prepare data for the following tests. - */ -add_task(function* test_initialize() { - for (let login of loginList()) { - Services.logins.addLogin(login); - } -}); - -/** - * Tests if the LoginManagerContextMenu returns the correct login items. - */ -add_task(function* test_contextMenuAddAndRemoveLogins() { - const DOCUMENT_CONTENT = "
"; - const INPUT_QUERY = "input[type='password']"; - - let testHostnames = [ - "http://www.example.com", - "http://www2.example.com", - "http://www3.example.com", - "http://empty.example.com", - ]; - - for (let hostname of testHostnames) { - do_print("test for hostname: " + hostname); - // Get expected logins for this test. - let logins = getExpectedLogins(hostname); - - // Create the logins menuitems fragment. - let {fragment, document} = createLoginsFragment(hostname, DOCUMENT_CONTENT, INPUT_QUERY); - - if (!logins.length) { - Assert.ok(fragment === null, "Null returned. No logins where found."); - continue; - } - let items = [...fragment.querySelectorAll("menuitem")]; - - // Check if the items are those expected to be listed. - Assert.ok(checkLoginItems(logins, items), "All expected logins found."); - document.body.appendChild(fragment); - - // Try to clear the fragment. - LoginManagerContextMenu.clearLoginsFromMenu(document); - Assert.equal(fragment.querySelectorAll("menuitem").length, 0, "All items correctly cleared."); - } - - Services.logins.removeAllLogins(); -}); - -/** - * Create a fragment with a menuitem for each login. - */ -function createLoginsFragment(url, content, elementQuery) { - const CHROME_URL = "chrome://mock-chrome"; - - // Create a mock document. - let document = MockDocument.createTestDocument(CHROME_URL, content); - let inputElement = document.querySelector(elementQuery); - MockDocument.mockOwnerDocumentProperty(inputElement, document, url); - - // We also need a simple mock Browser object for this test. - let browser = { - ownerDocument: document - }; - - let URI = Services.io.newURI(url, null, null); - return { - document, - fragment: LoginManagerContextMenu.addLoginsToMenu(inputElement, browser, URI), - }; -} - -/** - * Check if every login have it's corresponding menuitem. - * Duplicates and empty usernames have a date appended. - */ -function checkLoginItems(logins, items) { - function findDuplicates(unfilteredLoginList) { - var seen = new Set(); - var duplicates = new Set(); - for (let login of unfilteredLoginList) { - if (seen.has(login.username)) { - duplicates.add(login.username); - } - seen.add(login.username); - } - return duplicates; - } - let duplicates = findDuplicates(logins); - - let dateAndTimeFormatter = new Intl.DateTimeFormat(undefined, - { day: "numeric", month: "short", year: "numeric" }); - for (let login of logins) { - if (login.username && !duplicates.has(login.username)) { - // If login is not duplicate and we can't find an item for it, fail. - if (!items.find(item => item.label == login.username)) { - return false; - } - continue; - } - - let meta = login.QueryInterface(Ci.nsILoginMetaInfo); - let time = dateAndTimeFormatter.format(new Date(meta.timePasswordChanged)); - // If login is duplicate, check if we have a login item with appended date. - if (login.username && !items.find(item => item.label == login.username + " (" + time + ")")) { - return false; - } - // If login is empty, check if we have a login item with appended date. - if (!login.username && - !items.find(item => item.label == _stringBundle.GetStringFromName("noUsername") + " (" + time + ")")) { - return false; - } - } - return true; -} - -/** - * Gets the list of expected logins for a hostname. - */ -function getExpectedLogins(hostname) { - return Services.logins.getAllLogins().filter(entry => entry["hostname"] === hostname); -} - -function loginList() { - return [ - new LoginInfo("http://www.example.com", "http://www.example.com", null, - "username1", "password", - "form_field_username", "form_field_password"), - - new LoginInfo("http://www.example.com", "http://www.example.com", null, - "username2", "password", - "form_field_username", "form_field_password"), - - new LoginInfo("http://www2.example.com", "http://www.example.com", null, - "username", "password", - "form_field_username", "form_field_password"), - new LoginInfo("http://www2.example.com", "http://www2.example.com", null, - "username", "password2", - "form_field_username", "form_field_password"), - new LoginInfo("http://www2.example.com", "http://www2.example.com", null, - "username2", "password2", - "form_field_username", "form_field_password"), - - new LoginInfo("http://www3.example.com", "http://www.example.com", null, - "", "password", - "form_field_username", "form_field_password"), - new LoginInfo("http://www3.example.com", "http://www3.example.com", null, - "", "password2", - "form_field_username", "form_field_password"), - ]; -} diff --git a/toolkit/components/passwordmgr/test/unit/test_dedupeLogins.js b/toolkit/components/passwordmgr/test/unit/test_dedupeLogins.js deleted file mode 100644 index d688a6dbf..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_dedupeLogins.js +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Test LoginHelper.dedupeLogins - */ - -"use strict"; - -Cu.import("resource://gre/modules/LoginHelper.jsm"); - -const DOMAIN1_HTTP_TO_HTTP_U1_P1 = TestData.formLogin({ - timePasswordChanged: 3000, - timeLastUsed: 2000, -}); -const DOMAIN1_HTTP_TO_HTTP_U1_P2 = TestData.formLogin({ - password: "password two", -}); -const DOMAIN1_HTTP_TO_HTTP_U2_P2 = TestData.formLogin({ - password: "password two", - username: "username two", -}); -const DOMAIN1_HTTPS_TO_HTTPS_U1_P1 = TestData.formLogin({ - formSubmitURL: "http://www.example.com", - hostname: "https://www3.example.com", - timePasswordChanged: 4000, - timeLastUsed: 1000, -}); -const DOMAIN1_HTTPS_TO_EMPTY_U1_P1 = TestData.formLogin({ - formSubmitURL: "", - hostname: "https://www3.example.com", -}); -const DOMAIN1_HTTPS_TO_EMPTYU_P1 = TestData.formLogin({ - hostname: "https://www3.example.com", - username: "", -}); -const DOMAIN1_HTTP_AUTH = TestData.authLogin({ - hostname: "http://www3.example.com", -}); -const DOMAIN1_HTTPS_AUTH = TestData.authLogin({ - hostname: "https://www3.example.com", -}); - - -add_task(function test_dedupeLogins() { - // [description, expectedOutput, dedupe arg. 0, dedupe arg 1, ...] - let testcases = [ - [ - "exact dupes", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - [], // force no resolveBy logic to test behavior of preferring the first.. - ], - [ - "default uniqueKeys is un + pw", - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P2], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P2], - undefined, - [], - ], - [ - "same usernames, different passwords, dedupe username only", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P2], - ["username"], - [], - ], - [ - "same un+pw, different scheme", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - undefined, - [], - ], - [ - "same un+pw, different scheme, reverse order", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - [], - ], - [ - "same un+pw, different scheme, include hostname", - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - ["hostname", "username", "password"], - [], - ], - [ - "empty username is not deduped with non-empty", - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_EMPTYU_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_EMPTYU_P1], - undefined, - [], - ], - [ - "empty username is deduped with same passwords", - [DOMAIN1_HTTPS_TO_EMPTYU_P1], - [DOMAIN1_HTTPS_TO_EMPTYU_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - ["password"], - [], - ], - [ - "mix of form and HTTP auth", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTP_AUTH], - undefined, - [], - ], - ]; - - for (let tc of testcases) { - let description = tc.shift(); - let expected = tc.shift(); - let actual = LoginHelper.dedupeLogins(...tc); - Assert.strictEqual(actual.length, expected.length, `Check: ${description}`); - for (let [i, login] of expected.entries()) { - Assert.strictEqual(actual[i], login, `Check index ${i}`); - } - } -}); - - -add_task(function* test_dedupeLogins_resolveBy() { - Assert.ok(DOMAIN1_HTTP_TO_HTTP_U1_P1.timeLastUsed > DOMAIN1_HTTPS_TO_HTTPS_U1_P1.timeLastUsed, - "Sanity check timeLastUsed difference"); - Assert.ok(DOMAIN1_HTTP_TO_HTTP_U1_P1.timePasswordChanged < DOMAIN1_HTTPS_TO_HTTPS_U1_P1.timePasswordChanged, - "Sanity check timePasswordChanged difference"); - - let testcases = [ - [ - "default resolveBy is timeLastUsed", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - ], - [ - "default resolveBy is timeLastUsed, reversed input", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - ], - [ - "resolveBy timeLastUsed + timePasswordChanged", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["timeLastUsed", "timePasswordChanged"], - ], - [ - "resolveBy timeLastUsed + timePasswordChanged, reversed input", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - undefined, - ["timeLastUsed", "timePasswordChanged"], - ], - [ - "resolveBy timePasswordChanged", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["timePasswordChanged"], - ], - [ - "resolveBy timePasswordChanged, reversed", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - undefined, - ["timePasswordChanged"], - ], - [ - "resolveBy timePasswordChanged + timeLastUsed", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["timePasswordChanged", "timeLastUsed"], - ], - [ - "resolveBy timePasswordChanged + timeLastUsed, reversed", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - undefined, - ["timePasswordChanged", "timeLastUsed"], - ], - [ - "resolveBy scheme + timePasswordChanged, prefer HTTP", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["scheme", "timePasswordChanged"], - DOMAIN1_HTTP_TO_HTTP_U1_P1.hostname, - ], - [ - "resolveBy scheme + timePasswordChanged, prefer HTTP, reversed input", - [DOMAIN1_HTTP_TO_HTTP_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - undefined, - ["scheme", "timePasswordChanged"], - DOMAIN1_HTTP_TO_HTTP_U1_P1.hostname, - ], - [ - "resolveBy scheme + timePasswordChanged, prefer HTTPS", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["scheme", "timePasswordChanged"], - DOMAIN1_HTTPS_TO_HTTPS_U1_P1.hostname, - ], - [ - "resolveBy scheme + timePasswordChanged, prefer HTTPS, reversed input", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTP_TO_HTTP_U1_P1, DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - undefined, - ["scheme", "timePasswordChanged"], - DOMAIN1_HTTPS_TO_HTTPS_U1_P1.hostname, - ], - [ - "resolveBy scheme HTTP auth", - [DOMAIN1_HTTPS_AUTH], - [DOMAIN1_HTTP_AUTH, DOMAIN1_HTTPS_AUTH], - undefined, - ["scheme"], - DOMAIN1_HTTPS_AUTH.hostname, - ], - [ - "resolveBy scheme HTTP auth, reversed input", - [DOMAIN1_HTTPS_AUTH], - [DOMAIN1_HTTPS_AUTH, DOMAIN1_HTTP_AUTH], - undefined, - ["scheme"], - DOMAIN1_HTTPS_AUTH.hostname, - ], - [ - "resolveBy scheme, empty form submit URL", - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1], - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTPS_TO_EMPTY_U1_P1], - undefined, - ["scheme"], - DOMAIN1_HTTPS_TO_HTTPS_U1_P1.hostname, - ], - ]; - - for (let tc of testcases) { - let description = tc.shift(); - let expected = tc.shift(); - let actual = LoginHelper.dedupeLogins(...tc); - Assert.strictEqual(actual.length, expected.length, `Check: ${description}`); - for (let [i, login] of expected.entries()) { - Assert.strictEqual(actual[i], login, `Check index ${i}`); - } - } - -}); - -add_task(function* test_dedupeLogins_preferredOriginMissing() { - let testcases = [ - [ - "resolveBy scheme + timePasswordChanged, missing preferredOrigin", - /preferredOrigin/, - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["scheme", "timePasswordChanged"], - ], - [ - "resolveBy timePasswordChanged + scheme, missing preferredOrigin", - /preferredOrigin/, - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["timePasswordChanged", "scheme"], - ], - [ - "resolveBy scheme + timePasswordChanged, empty preferredOrigin", - /preferredOrigin/, - [DOMAIN1_HTTPS_TO_HTTPS_U1_P1, DOMAIN1_HTTP_TO_HTTP_U1_P1], - undefined, - ["scheme", "timePasswordChanged"], - "", - ], - ]; - - for (let tc of testcases) { - let description = tc.shift(); - let expectedException = tc.shift(); - Assert.throws(() => { - LoginHelper.dedupeLogins(...tc); - }, expectedException, `Check: ${description}`); - } -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_disabled_hosts.js b/toolkit/components/passwordmgr/test/unit/test_disabled_hosts.js deleted file mode 100644 index ff3b7e868..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_disabled_hosts.js +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests getLoginSavingEnabled, setLoginSavingEnabled, and getAllDisabledHosts. - */ - -"use strict"; - -// Tests - -/** - * Tests setLoginSavingEnabled and getAllDisabledHosts. - */ -add_task(function test_setLoginSavingEnabled_getAllDisabledHosts() -{ - // Add some disabled hosts, and verify that different schemes for the same - // domain are considered different hosts. - let hostname1 = "http://disabled1.example.com"; - let hostname2 = "http://disabled2.example.com"; - let hostname3 = "https://disabled2.example.com"; - Services.logins.setLoginSavingEnabled(hostname1, false); - Services.logins.setLoginSavingEnabled(hostname2, false); - Services.logins.setLoginSavingEnabled(hostname3, false); - - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - [hostname1, hostname2, hostname3]); - - // Adding the same host twice should not result in an error. - Services.logins.setLoginSavingEnabled(hostname2, false); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - [hostname1, hostname2, hostname3]); - - // Removing a disabled host should work. - Services.logins.setLoginSavingEnabled(hostname2, true); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - [hostname1, hostname3]); - - // Removing the last disabled host should work. - Services.logins.setLoginSavingEnabled(hostname1, true); - Services.logins.setLoginSavingEnabled(hostname3, true); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - []); -}); - -/** - * Tests setLoginSavingEnabled and getLoginSavingEnabled. - */ -add_task(function test_setLoginSavingEnabled_getLoginSavingEnabled() -{ - let hostname1 = "http://disabled.example.com"; - let hostname2 = "https://disabled.example.com"; - - // Hosts should not be disabled by default. - do_check_true(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_true(Services.logins.getLoginSavingEnabled(hostname2)); - - // Test setting initial values. - Services.logins.setLoginSavingEnabled(hostname1, false); - Services.logins.setLoginSavingEnabled(hostname2, true); - do_check_false(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_true(Services.logins.getLoginSavingEnabled(hostname2)); - - // Test changing values. - Services.logins.setLoginSavingEnabled(hostname1, true); - Services.logins.setLoginSavingEnabled(hostname2, false); - do_check_true(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_false(Services.logins.getLoginSavingEnabled(hostname2)); - - // Clean up. - Services.logins.setLoginSavingEnabled(hostname2, true); -}); - -/** - * Tests setLoginSavingEnabled with invalid NUL characters in the hostname. - */ -add_task(function test_setLoginSavingEnabled_invalid_characters() -{ - let hostname = "http://null\0X.example.com"; - Assert.throws(() => Services.logins.setLoginSavingEnabled(hostname, false), - /Invalid hostname/); - - // Verify that no data was stored by the previous call. - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - []); -}); - -/** - * Tests different values of the "signon.rememberSignons" property. - */ -add_task(function test_rememberSignons() -{ - let hostname1 = "http://example.com"; - let hostname2 = "http://localhost"; - - // The default value for the preference should be true. - do_check_true(Services.prefs.getBoolPref("signon.rememberSignons")); - - // Hosts should not be disabled by default. - Services.logins.setLoginSavingEnabled(hostname1, false); - do_check_false(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_true(Services.logins.getLoginSavingEnabled(hostname2)); - - // Disable storage of saved passwords globally. - Services.prefs.setBoolPref("signon.rememberSignons", false); - do_register_cleanup( - () => Services.prefs.clearUserPref("signon.rememberSignons")); - - // All hosts should now appear disabled. - do_check_false(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_false(Services.logins.getLoginSavingEnabled(hostname2)); - - // The list of disabled hosts should be unaltered. - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - [hostname1]); - - // Changing values with the preference set should work. - Services.logins.setLoginSavingEnabled(hostname1, true); - Services.logins.setLoginSavingEnabled(hostname2, false); - - // All hosts should still appear disabled. - do_check_false(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_false(Services.logins.getLoginSavingEnabled(hostname2)); - - // The list of disabled hosts should have been changed. - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - [hostname2]); - - // Enable storage of saved passwords again. - Services.prefs.setBoolPref("signon.rememberSignons", true); - - // Hosts should now appear enabled as requested. - do_check_true(Services.logins.getLoginSavingEnabled(hostname1)); - do_check_false(Services.logins.getLoginSavingEnabled(hostname2)); - - // Clean up. - Services.logins.setLoginSavingEnabled(hostname2, true); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - []); -}); - -/** - * Tests storing disabled hosts with non-ASCII characters where IDN is supported. - */ -add_task(function* test_storage_setLoginSavingEnabled_nonascii_IDN_is_supported() -{ - let hostname = "http://大.net"; - let encoding = "http://xn--pss.net"; - - // Test adding disabled host with nonascii URL (http://大.net). - Services.logins.setLoginSavingEnabled(hostname, false); - yield* LoginTestUtils.reloadData(); - Assert.equal(Services.logins.getLoginSavingEnabled(hostname), false); - Assert.equal(Services.logins.getLoginSavingEnabled(encoding), false); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), [hostname]); - - LoginTestUtils.clearData(); - - // Test adding disabled host with IDN ("http://xn--pss.net"). - Services.logins.setLoginSavingEnabled(encoding, false); - yield* LoginTestUtils.reloadData(); - Assert.equal(Services.logins.getLoginSavingEnabled(hostname), false); - Assert.equal(Services.logins.getLoginSavingEnabled(encoding), false); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), [hostname]); - - LoginTestUtils.clearData(); -}); - -/** - * Tests storing disabled hosts with non-ASCII characters where IDN is not supported. - */ -add_task(function* test_storage_setLoginSavingEnabled_nonascii_IDN_not_supported() -{ - let hostname = "http://√.com"; - let encoding = "http://xn--19g.com"; - - // Test adding disabled host with nonascii URL (http://√.com). - Services.logins.setLoginSavingEnabled(hostname, false); - yield* LoginTestUtils.reloadData(); - Assert.equal(Services.logins.getLoginSavingEnabled(hostname), false); - Assert.equal(Services.logins.getLoginSavingEnabled(encoding), false); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), [encoding]); - - LoginTestUtils.clearData(); - - // Test adding disabled host with IDN ("http://xn--19g.com"). - Services.logins.setLoginSavingEnabled(encoding, false); - yield* LoginTestUtils.reloadData(); - Assert.equal(Services.logins.getLoginSavingEnabled(hostname), false); - Assert.equal(Services.logins.getLoginSavingEnabled(encoding), false); - LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), [encoding]); - - LoginTestUtils.clearData(); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_getFormFields.js b/toolkit/components/passwordmgr/test/unit/test_getFormFields.js deleted file mode 100644 index 46912ab8f..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_getFormFields.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Test for LoginManagerContent._getFormFields. - */ - -"use strict"; - -// Services.prefs.setBoolPref("signon.debug", true); - -Cu.importGlobalProperties(["URL"]); - -const LMCBackstagePass = Cu.import("resource://gre/modules/LoginManagerContent.jsm"); -const { LoginManagerContent, LoginFormFactory } = LMCBackstagePass; -const TESTCASES = [ - { - description: "1 password field outside of a
", - document: ``, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "1 text field outside of a without a password field", - document: ``, - returnedFieldIDs: [null, null, null], - skipEmptyFields: undefined, - }, - { - description: "1 username & password field outside of a ", - document: ` - `, - returnedFieldIDs: ["un1", "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "1 username & password field in a ", - document: ` - - -
`, - returnedFieldIDs: ["un1", "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "4 empty password fields outside of a
", - document: ` - - - `, - returnedFieldIDs: [null, null, null], - skipEmptyFields: undefined, - }, - { - description: "4 password fields outside of a (1 empty, 3 full) with skipEmpty", - document: ` - - - `, - returnedFieldIDs: [null, null, null], - skipEmptyFields: true, - }, - { - description: "Form with 1 password field", - document: `
`, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "Form with 2 password fields", - document: `
`, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "1 password field in a form, 1 outside (not processed)", - document: `
`, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "1 password field in a form, 1 text field outside (not processed)", - document: `
`, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "1 text field in a form, 1 password field outside (not processed)", - document: `
`, - returnedFieldIDs: [null, null, null], - skipEmptyFields: undefined, - }, - { - description: "2 password fields outside of a
with 1 linked via @form", - document: ` -
`, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: undefined, - }, - { - description: "2 password fields outside of a
with 1 linked via @form + skipEmpty", - document: ` -
`, - returnedFieldIDs: [null, null, null], - skipEmptyFields: true, - }, - { - description: "2 password fields outside of a
with 1 linked via @form + skipEmpty with 1 empty", - document: ` -
`, - returnedFieldIDs: [null, "pw1", null], - skipEmptyFields: true, - }, -]; - -for (let tc of TESTCASES) { - do_print("Sanity checking the testcase: " + tc.description); - - (function() { - let testcase = tc; - add_task(function*() { - do_print("Starting testcase: " + testcase.description); - let document = MockDocument.createTestDocument("http://localhost:8080/test/", - testcase.document); - - let input = document.querySelector("input"); - MockDocument.mockOwnerDocumentProperty(input, document, "http://localhost:8080/test/"); - - let formLike = LoginFormFactory.createFromField(input); - - let actual = LoginManagerContent._getFormFields(formLike, - testcase.skipEmptyFields, - new Set()); - - Assert.strictEqual(testcase.returnedFieldIDs.length, 3, - "_getFormFields returns 3 elements"); - - for (let i = 0; i < testcase.returnedFieldIDs.length; i++) { - let expectedID = testcase.returnedFieldIDs[i]; - if (expectedID === null) { - Assert.strictEqual(actual[i], expectedID, - "Check returned field " + i + " is null"); - } else { - Assert.strictEqual(actual[i].id, expectedID, - "Check returned field " + i + " ID"); - } - } - }); - })(); -} diff --git a/toolkit/components/passwordmgr/test/unit/test_getPasswordFields.js b/toolkit/components/passwordmgr/test/unit/test_getPasswordFields.js deleted file mode 100644 index 08fa422ab..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_getPasswordFields.js +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Test for LoginManagerContent._getPasswordFields using LoginFormFactory. - */ - -"use strict"; - -const LMCBackstagePass = Cu.import("resource://gre/modules/LoginManagerContent.jsm"); -const { LoginManagerContent, LoginFormFactory } = LMCBackstagePass; -const TESTCASES = [ - { - description: "Empty document", - document: ``, - returnedFieldIDsByFormLike: [], - skipEmptyFields: undefined, - }, - { - description: "Non-password input with no
present", - document: ``, - // Only the IDs of password fields should be in this array - returnedFieldIDsByFormLike: [[]], - skipEmptyFields: undefined, - }, - { - description: "1 password field outside of a ", - document: ``, - returnedFieldIDsByFormLike: [["pw1"]], - skipEmptyFields: undefined, - }, - { - description: "4 empty password fields outside of a ", - document: ` - - - `, - returnedFieldIDsByFormLike: [[]], - skipEmptyFields: undefined, - }, - { - description: "4 password fields outside of a (1 empty, 3 full) with skipEmpty", - document: ` - - - `, - returnedFieldIDsByFormLike: [["pw2", "pw3", "pw4"]], - skipEmptyFields: true, - }, - { - description: "Form with 1 password field", - document: `
`, - returnedFieldIDsByFormLike: [["pw1"]], - skipEmptyFields: undefined, - }, - { - description: "Form with 2 password fields", - document: `
`, - returnedFieldIDsByFormLike: [["pw1", "pw2"]], - skipEmptyFields: undefined, - }, - { - description: "1 password field in a form, 1 outside", - document: `
`, - returnedFieldIDsByFormLike: [["pw1"], ["pw2"]], - skipEmptyFields: undefined, - }, - { - description: "2 password fields outside of a
with 1 linked via @form", - document: ` -
`, - returnedFieldIDsByFormLike: [["pw1"], ["pw2"]], - skipEmptyFields: undefined, - }, - { - description: "2 password fields outside of a
with 1 linked via @form + skipEmpty", - document: ` -
`, - returnedFieldIDsByFormLike: [[], []], - skipEmptyFields: true, - }, - { - description: "skipEmptyFields should also skip white-space only fields", - document: ` - - -
`, - returnedFieldIDsByFormLike: [[], []], - skipEmptyFields: true, - }, - { - description: "2 password fields outside of a
with 1 linked via @form + skipEmpty with 1 empty", - document: ` -
`, - returnedFieldIDsByFormLike: [["pw1"], []], - skipEmptyFields: true, - }, -]; - -for (let tc of TESTCASES) { - do_print("Sanity checking the testcase: " + tc.description); - - (function() { - let testcase = tc; - add_task(function*() { - do_print("Starting testcase: " + testcase.description); - let document = MockDocument.createTestDocument("http://localhost:8080/test/", - testcase.document); - - let mapRootElementToFormLike = new Map(); - for (let input of document.querySelectorAll("input")) { - let formLike = LoginFormFactory.createFromField(input); - let existingFormLike = mapRootElementToFormLike.get(formLike.rootElement); - if (!existingFormLike) { - mapRootElementToFormLike.set(formLike.rootElement, formLike); - continue; - } - - // If the formLike is already present, ensure that the properties are the same. - do_print("Checking if the new FormLike for the same root has the same properties"); - formLikeEqual(formLike, existingFormLike); - } - - Assert.strictEqual(mapRootElementToFormLike.size, testcase.returnedFieldIDsByFormLike.length, - "Check the correct number of different formLikes were returned"); - - let formLikeIndex = -1; - for (let formLikeFromInput of mapRootElementToFormLike.values()) { - formLikeIndex++; - let pwFields = LoginManagerContent._getPasswordFields(formLikeFromInput, - testcase.skipEmptyFields); - - if (formLikeFromInput.rootElement instanceof Ci.nsIDOMHTMLFormElement) { - let formLikeFromForm = LoginFormFactory.createFromForm(formLikeFromInput.rootElement); - do_print("Checking that the FormLike created for the
matches" + - " the one from a password field"); - formLikeEqual(formLikeFromInput, formLikeFromForm); - } - - - if (testcase.returnedFieldIDsByFormLike[formLikeIndex].length === 0) { - Assert.strictEqual(pwFields, null, - "If no password fields were found null should be returned"); - } else { - Assert.strictEqual(pwFields.length, - testcase.returnedFieldIDsByFormLike[formLikeIndex].length, - "Check the # of password fields for formLike #" + formLikeIndex); - } - - for (let i = 0; i < testcase.returnedFieldIDsByFormLike[formLikeIndex].length; i++) { - let expectedID = testcase.returnedFieldIDsByFormLike[formLikeIndex][i]; - Assert.strictEqual(pwFields[i].element.id, expectedID, - "Check password field " + i + " ID"); - } - } - }); - })(); -} diff --git a/toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js b/toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js deleted file mode 100644 index f2773ec62..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_getPasswordOrigin.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Test for LoginUtils._getPasswordOrigin - */ - -"use strict"; - -const LMCBackstagePass = Cu.import("resource://gre/modules/LoginManagerContent.jsm"); -const TESTCASES = [ - ["javascript:void(0);", null], - ["javascript:void(0);", "javascript:", true], - ["chrome://MyAccount", null], - ["data:text/html,example", null], - ["http://username:password@example.com:80/foo?bar=baz#fragment", "http://example.com", true], - ["http://127.0.0.1:80/foo", "http://127.0.0.1"], - ["http://[::1]:80/foo", "http://[::1]"], - ["http://example.com:8080/foo", "http://example.com:8080"], - ["http://127.0.0.1:8080/foo", "http://127.0.0.1:8080", true], - ["http://[::1]:8080/foo", "http://[::1]:8080"], - ["https://example.com:443/foo", "https://example.com"], - ["https://[::1]:443/foo", "https://[::1]"], - ["https://[::1]:8443/foo", "https://[::1]:8443"], - ["ftp://username:password@[::1]:2121/foo", "ftp://[::1]:2121"], -]; - -for (let [input, expected, allowJS] of TESTCASES) { - let actual = LMCBackstagePass.LoginUtils._getPasswordOrigin(input, allowJS); - Assert.strictEqual(actual, expected, "Checking: " + input); -} diff --git a/toolkit/components/passwordmgr/test/unit/test_isOriginMatching.js b/toolkit/components/passwordmgr/test/unit/test_isOriginMatching.js deleted file mode 100644 index 660910dff..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_isOriginMatching.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Test LoginHelper.isOriginMatching - */ - -"use strict"; - -Cu.import("resource://gre/modules/LoginHelper.jsm"); - -add_task(function test_isOriginMatching() { - let testcases = [ - // Index 0 holds the expected return value followed by arguments to isOriginMatching. - [true, "http://example.com", "http://example.com"], - [true, "http://example.com:8080", "http://example.com:8080"], - [true, "https://example.com", "https://example.com"], - [true, "https://example.com:8443", "https://example.com:8443"], - [false, "http://example.com", "http://mozilla.org"], - [false, "http://example.com", "http://example.com:8080"], - [false, "https://example.com", "http://example.com"], - [false, "https://example.com", "https://mozilla.org"], - [false, "http://example.com", "http://sub.example.com"], - [false, "https://example.com", "https://sub.example.com"], - [false, "http://example.com", "https://example.com:8443"], - [false, "http://example.com:8080", "http://example.com:8081"], - [false, "http://example.com", ""], - [false, "", "http://example.com"], - [true, "http://example.com", "https://example.com", { schemeUpgrades: true }], - [true, "https://example.com", "https://example.com", { schemeUpgrades: true }], - [true, "http://example.com:8080", "http://example.com:8080", { schemeUpgrades: true }], - [true, "https://example.com:8443", "https://example.com:8443", { schemeUpgrades: true }], - [false, "https://example.com", "http://example.com", { schemeUpgrades: true }], // downgrade - [false, "http://example.com:8080", "https://example.com", { schemeUpgrades: true }], // port mismatch - [false, "http://example.com", "https://example.com:8443", { schemeUpgrades: true }], // port mismatch - [false, "http://sub.example.com", "http://example.com", { schemeUpgrades: true }], - ]; - for (let tc of testcases) { - let expected = tc.shift(); - Assert.strictEqual(LoginHelper.isOriginMatching(...tc), expected, - "Check " + JSON.stringify(tc)); - } -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_legacy_empty_formSubmitURL.js b/toolkit/components/passwordmgr/test/unit/test_legacy_empty_formSubmitURL.js deleted file mode 100644 index 4e16aa267..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_legacy_empty_formSubmitURL.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the legacy case of a login store containing entries that have an empty - * string in the formSubmitURL field. - * - * In normal conditions, for the purpose of login autocomplete, HTML forms are - * identified using both the prePath of the URI on which they are located, and - * the prePath of the URI where the data will be submitted. This is represented - * by the hostname and formSubmitURL properties of the stored nsILoginInfo. - * - * When a new login for use in forms is saved (after the user replies to the - * password prompt), it is always stored with both the hostname and the - * formSubmitURL (that will be equal to the hostname when the form has no - * "action" attribute). - * - * When the same form is displayed again, the password is autocompleted. If - * there is another form on the same site that submits to a different site, it - * is considered a different form, so the password is not autocompleted, but a - * new password can be stored for the other form. - * - * However, the login database might contain data for an nsILoginInfo that has a - * valid hostname, but an empty formSubmitURL. This means that the login - * applies to all forms on the site, regardless of where they submit data to. - * - * A site can have at most one such login, and in case it is present, then it is - * not possible to store separate logins for forms on the same site that submit - * data to different sites. - * - * The only way to have such condition is to be using logins that were initially - * saved by a very old version of the browser, or because of data manually added - * by an extension in an old version. - */ - -"use strict"; - -// Tests - -/** - * Adds a login with an empty formSubmitURL, then it verifies that no other - * form logins can be added for the same host. - */ -add_task(function test_addLogin_wildcard() -{ - let loginInfo = TestData.formLogin({ hostname: "http://any.example.com", - formSubmitURL: "" }); - Services.logins.addLogin(loginInfo); - - // Normal form logins cannot be added anymore. - loginInfo = TestData.formLogin({ hostname: "http://any.example.com" }); - Assert.throws(() => Services.logins.addLogin(loginInfo), /already exists/); - - // Authentication logins can still be added. - loginInfo = TestData.authLogin({ hostname: "http://any.example.com" }); - Services.logins.addLogin(loginInfo); - - // Form logins can be added for other hosts. - loginInfo = TestData.formLogin({ hostname: "http://other.example.com" }); - Services.logins.addLogin(loginInfo); -}); - -/** - * Verifies that findLogins, searchLogins, and countLogins include all logins - * that have an empty formSubmitURL in the store, even when a formSubmitURL is - * specified. - */ -add_task(function test_search_all_wildcard() -{ - // Search a given formSubmitURL on any host. - let matchData = newPropertyBag({ formSubmitURL: "http://www.example.com" }); - do_check_eq(Services.logins.searchLogins({}, matchData).length, 2); - - do_check_eq(Services.logins.findLogins({}, "", "http://www.example.com", - null).length, 2); - - do_check_eq(Services.logins.countLogins("", "http://www.example.com", - null), 2); - - // Restrict the search to one host. - matchData.setProperty("hostname", "http://any.example.com"); - do_check_eq(Services.logins.searchLogins({}, matchData).length, 1); - - do_check_eq(Services.logins.findLogins({}, "http://any.example.com", - "http://www.example.com", - null).length, 1); - - do_check_eq(Services.logins.countLogins("http://any.example.com", - "http://www.example.com", - null), 1); -}); - -/** - * Verifies that specifying an empty string for formSubmitURL in searchLogins - * includes only logins that have an empty formSubmitURL in the store. - */ -add_task(function test_searchLogins_wildcard() -{ - let logins = Services.logins.searchLogins({}, - newPropertyBag({ formSubmitURL: "" })); - - let loginInfo = TestData.formLogin({ hostname: "http://any.example.com", - formSubmitURL: "" }); - LoginTestUtils.assertLoginListsEqual(logins, [loginInfo]); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_legacy_validation.js b/toolkit/components/passwordmgr/test/unit/test_legacy_validation.js deleted file mode 100644 index 709bc9818..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_legacy_validation.js +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the legacy validation made when storing nsILoginInfo or disabled hosts. - * - * These rules exist because of limitations of the "signons.txt" storage file, - * that is not used anymore. They are still enforced by the Login Manager - * service, despite these values can now be safely stored in the back-end. - */ - -"use strict"; - -// Tests - -/** - * Tests legacy validation with addLogin. - */ -add_task(function test_addLogin_invalid_characters_legacy() -{ - // Test newlines and carriage returns in properties that contain URLs. - for (let testValue of ["http://newline\n.example.com", - "http://carriagereturn.example.com\r"]) { - let loginInfo = TestData.formLogin({ hostname: testValue }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't contain newlines/); - - loginInfo = TestData.formLogin({ formSubmitURL: testValue }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't contain newlines/); - - loginInfo = TestData.authLogin({ httpRealm: testValue }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't contain newlines/); - } - - // Test newlines and carriage returns in form field names. - for (let testValue of ["newline_field\n", "carriagereturn\r_field"]) { - let loginInfo = TestData.formLogin({ usernameField: testValue }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't contain newlines/); - - loginInfo = TestData.formLogin({ passwordField: testValue }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't contain newlines/); - } - - // Test a single dot as the value of usernameField and formSubmitURL. - let loginInfo = TestData.formLogin({ usernameField: "." }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't be periods/); - - loginInfo = TestData.formLogin({ formSubmitURL: "." }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /login values can't be periods/); - - // Test the sequence " (" inside the value of the "hostname" property. - loginInfo = TestData.formLogin({ hostname: "http://parens (.example.com" }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /bad parens in hostname/); -}); - -/** - * Tests legacy validation with setLoginSavingEnabled. - */ -add_task(function test_setLoginSavingEnabled_invalid_characters_legacy() -{ - for (let hostname of ["http://newline\n.example.com", - "http://carriagereturn.example.com\r", - "."]) { - Assert.throws(() => Services.logins.setLoginSavingEnabled(hostname, false), - /Invalid hostname/); - } -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_logins_change.js b/toolkit/components/passwordmgr/test/unit/test_logins_change.js deleted file mode 100644 index 79c6d2f54..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_logins_change.js +++ /dev/null @@ -1,384 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests methods that add, remove, and modify logins. - */ - -"use strict"; - -// Globals - -/** - * Verifies that the specified login is considered invalid by addLogin and by - * modifyLogin with both nsILoginInfo and nsIPropertyBag arguments. - * - * This test requires that the login store is empty. - * - * @param aLoginInfo - * nsILoginInfo corresponding to an invalid login. - * @param aExpectedError - * This argument is passed to the "Assert.throws" test to determine which - * error is expected from the modification functions. - */ -function checkLoginInvalid(aLoginInfo, aExpectedError) -{ - // Try to add the new login, and verify that no data is stored. - Assert.throws(() => Services.logins.addLogin(aLoginInfo), aExpectedError); - LoginTestUtils.checkLogins([]); - - // Add a login for the modification tests. - let testLogin = TestData.formLogin({ hostname: "http://modify.example.com" }); - Services.logins.addLogin(testLogin); - - // Try to modify the existing login using nsILoginInfo and nsIPropertyBag. - Assert.throws(() => Services.logins.modifyLogin(testLogin, aLoginInfo), - aExpectedError); - Assert.throws(() => Services.logins.modifyLogin(testLogin, newPropertyBag({ - hostname: aLoginInfo.hostname, - formSubmitURL: aLoginInfo.formSubmitURL, - httpRealm: aLoginInfo.httpRealm, - username: aLoginInfo.username, - password: aLoginInfo.password, - usernameField: aLoginInfo.usernameField, - passwordField: aLoginInfo.passwordField, - })), aExpectedError); - - // Verify that no data was stored by the previous calls. - LoginTestUtils.checkLogins([testLogin]); - Services.logins.removeLogin(testLogin); -} - -/** - * Verifies that two objects are not the same instance - * but have equal attributes. - * - * @param {Object} objectA - * An object to compare. - * - * @param {Object} objectB - * Another object to compare. - * - * @param {string[]} attributes - * Attributes to compare. - * - * @return true if all passed attributes are equal for both objects, false otherwise. - */ -function compareAttributes(objectA, objectB, attributes) { - // If it's the same object, we want to return false. - if (objectA == objectB) { - return false; - } - return attributes.every(attr => objectA[attr] == objectB[attr]); -} - -// Tests - -/** - * Tests that adding logins to the database works. - */ -add_task(function test_addLogin_removeLogin() -{ - // Each login from the test data should be valid and added to the list. - for (let loginInfo of TestData.loginList()) { - Services.logins.addLogin(loginInfo); - } - LoginTestUtils.checkLogins(TestData.loginList()); - - // Trying to add each login again should result in an error. - for (let loginInfo of TestData.loginList()) { - Assert.throws(() => Services.logins.addLogin(loginInfo), /already exists/); - } - - // Removing each login should succeed. - for (let loginInfo of TestData.loginList()) { - Services.logins.removeLogin(loginInfo); - } - - LoginTestUtils.checkLogins([]); -}); - -/** - * Tests invalid combinations of httpRealm and formSubmitURL. - * - * For an nsILoginInfo to be valid for storage, one of the two properties should - * be strictly equal to null, and the other must not be null or an empty string. - * - * The legacy case of an empty string in formSubmitURL and a null value in - * httpRealm is also supported for storage at the moment. - */ -add_task(function test_invalid_httpRealm_formSubmitURL() -{ - // httpRealm === null, formSubmitURL === null - checkLoginInvalid(TestData.formLogin({ formSubmitURL: null }), - /without a httpRealm or formSubmitURL/); - - // httpRealm === "", formSubmitURL === null - checkLoginInvalid(TestData.authLogin({ httpRealm: "" }), - /without a httpRealm or formSubmitURL/); - - // httpRealm === null, formSubmitURL === "" - // This is not enforced for now. - // checkLoginInvalid(TestData.formLogin({ formSubmitURL: "" }), - // /without a httpRealm or formSubmitURL/); - - // httpRealm === "", formSubmitURL === "" - checkLoginInvalid(TestData.formLogin({ formSubmitURL: "", httpRealm: "" }), - /both a httpRealm and formSubmitURL/); - - // !!httpRealm, !!formSubmitURL - checkLoginInvalid(TestData.formLogin({ httpRealm: "The HTTP Realm" }), - /both a httpRealm and formSubmitURL/); - - // httpRealm === "", !!formSubmitURL - checkLoginInvalid(TestData.formLogin({ httpRealm: "" }), - /both a httpRealm and formSubmitURL/); - - // !!httpRealm, formSubmitURL === "" - checkLoginInvalid(TestData.authLogin({ formSubmitURL: "" }), - /both a httpRealm and formSubmitURL/); -}); - -/** - * Tests null or empty values in required login properties. - */ -add_task(function test_missing_properties() -{ - checkLoginInvalid(TestData.formLogin({ hostname: null }), - /null or empty hostname/); - - checkLoginInvalid(TestData.formLogin({ hostname: "" }), - /null or empty hostname/); - - checkLoginInvalid(TestData.formLogin({ username: null }), - /null username/); - - checkLoginInvalid(TestData.formLogin({ password: null }), - /null or empty password/); - - checkLoginInvalid(TestData.formLogin({ password: "" }), - /null or empty password/); -}); - -/** - * Tests invalid NUL characters in nsILoginInfo properties. - */ -add_task(function test_invalid_characters() -{ - let loginList = [ - TestData.authLogin({ hostname: "http://null\0X.example.com" }), - TestData.authLogin({ httpRealm: "realm\0" }), - TestData.formLogin({ formSubmitURL: "http://null\0X.example.com" }), - TestData.formLogin({ usernameField: "field\0_null" }), - TestData.formLogin({ usernameField: ".\0" }), // Special single dot case - TestData.formLogin({ passwordField: "field\0_null" }), - TestData.formLogin({ username: "user\0name" }), - TestData.formLogin({ password: "pass\0word" }), - ]; - for (let loginInfo of loginList) { - checkLoginInvalid(loginInfo, /login values can't contain nulls/); - } -}); - -/** - * Tests removing a login that does not exists. - */ -add_task(function test_removeLogin_nonexisting() -{ - Assert.throws(() => Services.logins.removeLogin(TestData.formLogin()), - /No matching logins/); -}); - -/** - * Tests removing all logins at once. - */ -add_task(function test_removeAllLogins() -{ - for (let loginInfo of TestData.loginList()) { - Services.logins.addLogin(loginInfo); - } - Services.logins.removeAllLogins(); - LoginTestUtils.checkLogins([]); - - // The function should also work when there are no logins to delete. - Services.logins.removeAllLogins(); -}); - -/** - * Tests the modifyLogin function with an nsILoginInfo argument. - */ -add_task(function test_modifyLogin_nsILoginInfo() -{ - let loginInfo = TestData.formLogin(); - let updatedLoginInfo = TestData.formLogin({ - username: "new username", - password: "new password", - usernameField: "new_form_field_username", - passwordField: "new_form_field_password", - }); - let differentLoginInfo = TestData.authLogin(); - - // Trying to modify a login that does not exist should throw. - Assert.throws(() => Services.logins.modifyLogin(loginInfo, updatedLoginInfo), - /No matching logins/); - - // Add the first form login, then modify it to match the second. - Services.logins.addLogin(loginInfo); - Services.logins.modifyLogin(loginInfo, updatedLoginInfo); - - // The data should now match the second login. - LoginTestUtils.checkLogins([updatedLoginInfo]); - Assert.throws(() => Services.logins.modifyLogin(loginInfo, updatedLoginInfo), - /No matching logins/); - - // The login can be changed to have a different type and hostname. - Services.logins.modifyLogin(updatedLoginInfo, differentLoginInfo); - LoginTestUtils.checkLogins([differentLoginInfo]); - - // It is now possible to add a login with the old type and hostname. - Services.logins.addLogin(loginInfo); - LoginTestUtils.checkLogins([loginInfo, differentLoginInfo]); - - // Modifying a login to match an existing one should not be possible. - Assert.throws( - () => Services.logins.modifyLogin(loginInfo, differentLoginInfo), - /already exists/); - LoginTestUtils.checkLogins([loginInfo, differentLoginInfo]); - - LoginTestUtils.clearData(); -}); - -/** - * Tests the modifyLogin function with an nsIPropertyBag argument. - */ -add_task(function test_modifyLogin_nsIProperyBag() -{ - let loginInfo = TestData.formLogin(); - let updatedLoginInfo = TestData.formLogin({ - username: "new username", - password: "new password", - usernameField: "", - passwordField: "new_form_field_password", - }); - let differentLoginInfo = TestData.authLogin(); - let differentLoginProperties = newPropertyBag({ - hostname: differentLoginInfo.hostname, - formSubmitURL: differentLoginInfo.formSubmitURL, - httpRealm: differentLoginInfo.httpRealm, - username: differentLoginInfo.username, - password: differentLoginInfo.password, - usernameField: differentLoginInfo.usernameField, - passwordField: differentLoginInfo.passwordField, - }); - - // Trying to modify a login that does not exist should throw. - Assert.throws(() => Services.logins.modifyLogin(loginInfo, newPropertyBag()), - /No matching logins/); - - // Add the first form login, then modify it to match the second, changing - // only some of its properties and checking the behavior with an empty string. - Services.logins.addLogin(loginInfo); - Services.logins.modifyLogin(loginInfo, newPropertyBag({ - username: "new username", - password: "new password", - usernameField: "", - passwordField: "new_form_field_password", - })); - - // The data should now match the second login. - LoginTestUtils.checkLogins([updatedLoginInfo]); - Assert.throws(() => Services.logins.modifyLogin(loginInfo, newPropertyBag()), - /No matching logins/); - - // It is also possible to provide no properties to be modified. - Services.logins.modifyLogin(updatedLoginInfo, newPropertyBag()); - - // Specifying a null property for a required value should throw. - Assert.throws(() => Services.logins.modifyLogin(loginInfo, newPropertyBag({ - usernameField: null, - }))); - - // The login can be changed to have a different type and hostname. - Services.logins.modifyLogin(updatedLoginInfo, differentLoginProperties); - LoginTestUtils.checkLogins([differentLoginInfo]); - - // It is now possible to add a login with the old type and hostname. - Services.logins.addLogin(loginInfo); - LoginTestUtils.checkLogins([loginInfo, differentLoginInfo]); - - // Modifying a login to match an existing one should not be possible. - Assert.throws( - () => Services.logins.modifyLogin(loginInfo, differentLoginProperties), - /already exists/); - LoginTestUtils.checkLogins([loginInfo, differentLoginInfo]); - - LoginTestUtils.clearData(); -}); - -/** - * Tests the login deduplication function. - */ -add_task(function test_deduplicate_logins() { - // Different key attributes combinations and the amount of unique - // results expected for the TestData login list. - let keyCombinations = [ - { - keyset: ["username", "password"], - results: 13, - }, - { - keyset: ["hostname", "username"], - results: 17, - }, - { - keyset: ["hostname", "username", "password"], - results: 18, - }, - { - keyset: ["hostname", "username", "password", "formSubmitURL"], - results: 23, - }, - ]; - - let logins = TestData.loginList(); - - for (let testCase of keyCombinations) { - // Deduplicate the logins using the current testcase keyset. - let deduped = LoginHelper.dedupeLogins(logins, testCase.keyset); - Assert.equal(deduped.length, testCase.results, "Correct amount of results."); - - // Checks that every login after deduping is unique. - Assert.ok(deduped.every(loginA => - deduped.every(loginB => !compareAttributes(loginA, loginB, testCase.keyset)) - ), "Every login is unique."); - } -}); - -/** - * Ensure that the login deduplication function keeps the most recent login. - */ -add_task(function test_deduplicate_keeps_most_recent() { - // Logins to deduplicate. - let logins = [ - TestData.formLogin({timeLastUsed: Date.UTC(2004, 11, 4, 0, 0, 0)}), - TestData.formLogin({formSubmitURL: "http://example.com", timeLastUsed: Date.UTC(2015, 11, 4, 0, 0, 0)}), - ]; - - // Deduplicate the logins. - let deduped = LoginHelper.dedupeLogins(logins); - Assert.equal(deduped.length, 1, "Deduplicated the logins array."); - - // Verify that the remaining login have the most recent date. - let loginTimeLastUsed = deduped[0].QueryInterface(Ci.nsILoginMetaInfo).timeLastUsed; - Assert.equal(loginTimeLastUsed, Date.UTC(2015, 11, 4, 0, 0, 0), "Most recent login was kept."); - - // Deduplicate the reverse logins array. - deduped = LoginHelper.dedupeLogins(logins.reverse()); - Assert.equal(deduped.length, 1, "Deduplicated the reversed logins array."); - - // Verify that the remaining login have the most recent date. - loginTimeLastUsed = deduped[0].QueryInterface(Ci.nsILoginMetaInfo).timeLastUsed; - Assert.equal(loginTimeLastUsed, Date.UTC(2015, 11, 4, 0, 0, 0), "Most recent login was kept."); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_logins_decrypt_failure.js b/toolkit/components/passwordmgr/test/unit/test_logins_decrypt_failure.js deleted file mode 100644 index ffbedb4de..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_logins_decrypt_failure.js +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the case where there are logins that cannot be decrypted. - */ - -"use strict"; - -// Globals - -/** - * Resets the token used to decrypt logins. This is equivalent to resetting the - * master password when it is not known. - */ -function resetMasterPassword() -{ - let token = Cc["@mozilla.org/security/pk11tokendb;1"] - .getService(Ci.nsIPK11TokenDB).getInternalKeyToken(); - token.reset(); - token.changePassword("", ""); -} - -// Tests - -/** - * Resets the master password after some logins were added to the database. - */ -add_task(function test_logins_decrypt_failure() -{ - let logins = TestData.loginList(); - for (let loginInfo of logins) { - Services.logins.addLogin(loginInfo); - } - - // This makes the existing logins non-decryptable. - resetMasterPassword(); - - // These functions don't see the non-decryptable entries anymore. - do_check_eq(Services.logins.getAllLogins().length, 0); - do_check_eq(Services.logins.findLogins({}, "", "", "").length, 0); - do_check_eq(Services.logins.searchLogins({}, newPropertyBag()).length, 0); - Assert.throws(() => Services.logins.modifyLogin(logins[0], newPropertyBag()), - /No matching logins/); - Assert.throws(() => Services.logins.removeLogin(logins[0]), - /No matching logins/); - - // The function that counts logins sees the non-decryptable entries also. - do_check_eq(Services.logins.countLogins("", "", ""), logins.length); - - // Equivalent logins can be added. - for (let loginInfo of logins) { - Services.logins.addLogin(loginInfo); - } - LoginTestUtils.checkLogins(logins); - do_check_eq(Services.logins.countLogins("", "", ""), logins.length * 2); - - // Finding logins doesn't return the non-decryptable duplicates. - do_check_eq(Services.logins.findLogins({}, "http://www.example.com", - "", "").length, 1); - let matchData = newPropertyBag({ hostname: "http://www.example.com" }); - do_check_eq(Services.logins.searchLogins({}, matchData).length, 1); - - // Removing single logins does not remove non-decryptable logins. - for (let loginInfo of TestData.loginList()) { - Services.logins.removeLogin(loginInfo); - } - do_check_eq(Services.logins.getAllLogins().length, 0); - do_check_eq(Services.logins.countLogins("", "", ""), logins.length); - - // Removing all logins removes the non-decryptable entries also. - Services.logins.removeAllLogins(); - do_check_eq(Services.logins.getAllLogins().length, 0); - do_check_eq(Services.logins.countLogins("", "", ""), 0); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_logins_metainfo.js b/toolkit/components/passwordmgr/test/unit/test_logins_metainfo.js deleted file mode 100644 index 38344aa7d..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_logins_metainfo.js +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the handling of nsILoginMetaInfo by methods that add, remove, modify, - * and find logins. - */ - -"use strict"; - -// Globals - -XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator", - "@mozilla.org/uuid-generator;1", - "nsIUUIDGenerator"); - -var gLooksLikeUUIDRegex = /^\{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\}$/; - -/** - * Retrieves the only login among the current data that matches the hostname of - * the given nsILoginInfo. In case there is more than one login for the - * hostname, the test fails. - */ -function retrieveLoginMatching(aLoginInfo) -{ - let logins = Services.logins.findLogins({}, aLoginInfo.hostname, "", ""); - do_check_eq(logins.length, 1); - return logins[0].QueryInterface(Ci.nsILoginMetaInfo); -} - -/** - * Checks that the nsILoginInfo and nsILoginMetaInfo properties of two different - * login instances are equal. - */ -function assertMetaInfoEqual(aActual, aExpected) -{ - do_check_neq(aActual, aExpected); - - // Check the nsILoginInfo properties. - do_check_true(aActual.equals(aExpected)); - - // Check the nsILoginMetaInfo properties. - do_check_eq(aActual.guid, aExpected.guid); - do_check_eq(aActual.timeCreated, aExpected.timeCreated); - do_check_eq(aActual.timeLastUsed, aExpected.timeLastUsed); - do_check_eq(aActual.timePasswordChanged, aExpected.timePasswordChanged); - do_check_eq(aActual.timesUsed, aExpected.timesUsed); -} - -/** - * nsILoginInfo instances with or without nsILoginMetaInfo properties. - */ -var gLoginInfo1; -var gLoginInfo2; -var gLoginInfo3; - -/** - * nsILoginInfo instances reloaded with all the nsILoginMetaInfo properties. - * These are often used to provide the reference values to test against. - */ -var gLoginMetaInfo1; -var gLoginMetaInfo2; -var gLoginMetaInfo3; - -// Tests - -/** - * Prepare the test objects that will be used by the following tests. - */ -add_task(function test_initialize() -{ - // Use a reference time from ten minutes ago to initialize one instance of - // nsILoginMetaInfo, to test that reference times are updated when needed. - let baseTimeMs = Date.now() - 600000; - - gLoginInfo1 = TestData.formLogin(); - gLoginInfo2 = TestData.formLogin({ - hostname: "http://other.example.com", - guid: gUUIDGenerator.generateUUID().toString(), - timeCreated: baseTimeMs, - timeLastUsed: baseTimeMs + 2, - timePasswordChanged: baseTimeMs + 1, - timesUsed: 2, - }); - gLoginInfo3 = TestData.authLogin(); -}); - -/** - * Tests the behavior of addLogin with regard to metadata. The logins added - * here are also used by the following tests. - */ -add_task(function test_addLogin_metainfo() -{ - // Add a login without metadata to the database. - Services.logins.addLogin(gLoginInfo1); - - // The object provided to addLogin should not have been modified. - do_check_eq(gLoginInfo1.guid, null); - do_check_eq(gLoginInfo1.timeCreated, 0); - do_check_eq(gLoginInfo1.timeLastUsed, 0); - do_check_eq(gLoginInfo1.timePasswordChanged, 0); - do_check_eq(gLoginInfo1.timesUsed, 0); - - // A login with valid metadata should have been stored. - gLoginMetaInfo1 = retrieveLoginMatching(gLoginInfo1); - do_check_true(gLooksLikeUUIDRegex.test(gLoginMetaInfo1.guid)); - let creationTime = gLoginMetaInfo1.timeCreated; - LoginTestUtils.assertTimeIsAboutNow(creationTime); - do_check_eq(gLoginMetaInfo1.timeLastUsed, creationTime); - do_check_eq(gLoginMetaInfo1.timePasswordChanged, creationTime); - do_check_eq(gLoginMetaInfo1.timesUsed, 1); - - // Add a login without metadata to the database. - let originalLogin = gLoginInfo2.clone().QueryInterface(Ci.nsILoginMetaInfo); - Services.logins.addLogin(gLoginInfo2); - - // The object provided to addLogin should not have been modified. - assertMetaInfoEqual(gLoginInfo2, originalLogin); - - // A login with the provided metadata should have been stored. - gLoginMetaInfo2 = retrieveLoginMatching(gLoginInfo2); - assertMetaInfoEqual(gLoginMetaInfo2, gLoginInfo2); - - // Add an authentication login to the database before continuing. - Services.logins.addLogin(gLoginInfo3); - gLoginMetaInfo3 = retrieveLoginMatching(gLoginInfo3); - LoginTestUtils.checkLogins([gLoginInfo1, gLoginInfo2, gLoginInfo3]); -}); - -/** - * Tests that adding a login with a duplicate GUID throws an exception. - */ -add_task(function test_addLogin_metainfo_duplicate() -{ - let loginInfo = TestData.formLogin({ - hostname: "http://duplicate.example.com", - guid: gLoginMetaInfo2.guid, - }); - Assert.throws(() => Services.logins.addLogin(loginInfo), - /specified GUID already exists/); - - // Verify that no data was stored by the previous call. - LoginTestUtils.checkLogins([gLoginInfo1, gLoginInfo2, gLoginInfo3]); -}); - -/** - * Tests that the existing metadata is not changed when modifyLogin is called - * with an nsILoginInfo argument. - */ -add_task(function test_modifyLogin_nsILoginInfo_metainfo_ignored() -{ - let newLoginInfo = gLoginInfo1.clone().QueryInterface(Ci.nsILoginMetaInfo); - newLoginInfo.guid = gUUIDGenerator.generateUUID().toString(); - newLoginInfo.timeCreated = Date.now(); - newLoginInfo.timeLastUsed = Date.now(); - newLoginInfo.timePasswordChanged = Date.now(); - newLoginInfo.timesUsed = 12; - Services.logins.modifyLogin(gLoginInfo1, newLoginInfo); - - newLoginInfo = retrieveLoginMatching(gLoginInfo1); - assertMetaInfoEqual(newLoginInfo, gLoginMetaInfo1); -}); - -/** - * Tests the modifyLogin function with an nsIProperyBag argument. - */ -add_task(function test_modifyLogin_nsIProperyBag_metainfo() -{ - // Use a new reference time that is two minutes from now. - let newTimeMs = Date.now() + 120000; - let newUUIDValue = gUUIDGenerator.generateUUID().toString(); - - // Check that properties are changed as requested. - Services.logins.modifyLogin(gLoginInfo1, newPropertyBag({ - guid: newUUIDValue, - timeCreated: newTimeMs, - timeLastUsed: newTimeMs + 2, - timePasswordChanged: newTimeMs + 1, - timesUsed: 2, - })); - - gLoginMetaInfo1 = retrieveLoginMatching(gLoginInfo1); - do_check_eq(gLoginMetaInfo1.guid, newUUIDValue); - do_check_eq(gLoginMetaInfo1.timeCreated, newTimeMs); - do_check_eq(gLoginMetaInfo1.timeLastUsed, newTimeMs + 2); - do_check_eq(gLoginMetaInfo1.timePasswordChanged, newTimeMs + 1); - do_check_eq(gLoginMetaInfo1.timesUsed, 2); - - // Check that timePasswordChanged is updated when changing the password. - let originalLogin = gLoginInfo2.clone().QueryInterface(Ci.nsILoginMetaInfo); - Services.logins.modifyLogin(gLoginInfo2, newPropertyBag({ - password: "new password", - })); - gLoginInfo2.password = "new password"; - - gLoginMetaInfo2 = retrieveLoginMatching(gLoginInfo2); - do_check_eq(gLoginMetaInfo2.password, gLoginInfo2.password); - do_check_eq(gLoginMetaInfo2.timeCreated, originalLogin.timeCreated); - do_check_eq(gLoginMetaInfo2.timeLastUsed, originalLogin.timeLastUsed); - LoginTestUtils.assertTimeIsAboutNow(gLoginMetaInfo2.timePasswordChanged); - - // Check that timePasswordChanged is not set to the current time when changing - // the password and specifying a new value for the property at the same time. - Services.logins.modifyLogin(gLoginInfo2, newPropertyBag({ - password: "other password", - timePasswordChanged: newTimeMs, - })); - gLoginInfo2.password = "other password"; - - gLoginMetaInfo2 = retrieveLoginMatching(gLoginInfo2); - do_check_eq(gLoginMetaInfo2.password, gLoginInfo2.password); - do_check_eq(gLoginMetaInfo2.timeCreated, originalLogin.timeCreated); - do_check_eq(gLoginMetaInfo2.timeLastUsed, originalLogin.timeLastUsed); - do_check_eq(gLoginMetaInfo2.timePasswordChanged, newTimeMs); - - // Check the special timesUsedIncrement property. - Services.logins.modifyLogin(gLoginInfo2, newPropertyBag({ - timesUsedIncrement: 2, - })); - - gLoginMetaInfo2 = retrieveLoginMatching(gLoginInfo2); - do_check_eq(gLoginMetaInfo2.timeCreated, originalLogin.timeCreated); - do_check_eq(gLoginMetaInfo2.timeLastUsed, originalLogin.timeLastUsed); - do_check_eq(gLoginMetaInfo2.timePasswordChanged, newTimeMs); - do_check_eq(gLoginMetaInfo2.timesUsed, 4); -}); - -/** - * Tests that modifying a login to a duplicate GUID throws an exception. - */ -add_task(function test_modifyLogin_nsIProperyBag_metainfo_duplicate() -{ - Assert.throws(() => Services.logins.modifyLogin(gLoginInfo1, newPropertyBag({ - guid: gLoginInfo2.guid, - })), /specified GUID already exists/); - LoginTestUtils.checkLogins([gLoginInfo1, gLoginInfo2, gLoginInfo3]); -}); - -/** - * Tests searching logins using nsILoginMetaInfo properties. - */ -add_task(function test_searchLogins_metainfo() -{ - // Find by GUID. - let logins = Services.logins.searchLogins({}, newPropertyBag({ - guid: gLoginMetaInfo1.guid, - })); - do_check_eq(logins.length, 1); - let foundLogin = logins[0].QueryInterface(Ci.nsILoginMetaInfo); - assertMetaInfoEqual(foundLogin, gLoginMetaInfo1); - - // Find by timestamp. - logins = Services.logins.searchLogins({}, newPropertyBag({ - timePasswordChanged: gLoginMetaInfo2.timePasswordChanged, - })); - do_check_eq(logins.length, 1); - foundLogin = logins[0].QueryInterface(Ci.nsILoginMetaInfo); - assertMetaInfoEqual(foundLogin, gLoginMetaInfo2); - - // Find using two properties at the same time. - logins = Services.logins.searchLogins({}, newPropertyBag({ - guid: gLoginMetaInfo3.guid, - timePasswordChanged: gLoginMetaInfo3.timePasswordChanged, - })); - do_check_eq(logins.length, 1); - foundLogin = logins[0].QueryInterface(Ci.nsILoginMetaInfo); - assertMetaInfoEqual(foundLogin, gLoginMetaInfo3); -}); - -/** - * Tests that the default nsILoginManagerStorage module attached to the Login - * Manager service is able to save and reload nsILoginMetaInfo properties. - */ -add_task(function* test_storage_metainfo() -{ - yield* LoginTestUtils.reloadData(); - LoginTestUtils.checkLogins([gLoginInfo1, gLoginInfo2, gLoginInfo3]); - - assertMetaInfoEqual(retrieveLoginMatching(gLoginInfo1), gLoginMetaInfo1); - assertMetaInfoEqual(retrieveLoginMatching(gLoginInfo2), gLoginMetaInfo2); - assertMetaInfoEqual(retrieveLoginMatching(gLoginInfo3), gLoginMetaInfo3); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_logins_search.js b/toolkit/components/passwordmgr/test/unit/test_logins_search.js deleted file mode 100644 index 730771981..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_logins_search.js +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Tests methods that find specific logins in the store (findLogins, - * searchLogins, and countLogins). - * - * The getAllLogins method is not tested explicitly here, because it is used by - * all tests to verify additions, removals and modifications to the login store. - */ - -"use strict"; - -// Globals - -/** - * Returns a list of new nsILoginInfo objects that are a subset of the test - * data, built to match the specified query. - * - * @param aQuery - * Each property and value of this object restricts the search to those - * entries from the test data that match the property exactly. - */ -function buildExpectedLogins(aQuery) -{ - return TestData.loginList().filter( - entry => Object.keys(aQuery).every(name => entry[name] === aQuery[name])); -} - -/** - * Tests the searchLogins function. - * - * @param aQuery - * Each property and value of this object is translated to an entry in - * the nsIPropertyBag parameter of searchLogins. - * @param aExpectedCount - * Number of logins from the test data that should be found. The actual - * list of logins is obtained using the buildExpectedLogins helper, and - * this value is just used to verify that modifications to the test data - * don't make the current test meaningless. - */ -function checkSearchLogins(aQuery, aExpectedCount) -{ - do_print("Testing searchLogins for " + JSON.stringify(aQuery)); - - let expectedLogins = buildExpectedLogins(aQuery); - do_check_eq(expectedLogins.length, aExpectedCount); - - let outCount = {}; - let logins = Services.logins.searchLogins(outCount, newPropertyBag(aQuery)); - do_check_eq(outCount.value, expectedLogins.length); - LoginTestUtils.assertLoginListsEqual(logins, expectedLogins); -} - -/** - * Tests findLogins, searchLogins, and countLogins with the same query. - * - * @param aQuery - * The "hostname", "formSubmitURL", and "httpRealm" properties of this - * object are passed as parameters to findLogins and countLogins. The - * same object is then passed to the checkSearchLogins function. - * @param aExpectedCount - * Number of logins from the test data that should be found. The actual - * list of logins is obtained using the buildExpectedLogins helper, and - * this value is just used to verify that modifications to the test data - * don't make the current test meaningless. - */ -function checkAllSearches(aQuery, aExpectedCount) -{ - do_print("Testing all search functions for " + JSON.stringify(aQuery)); - - let expectedLogins = buildExpectedLogins(aQuery); - do_check_eq(expectedLogins.length, aExpectedCount); - - // The findLogins and countLogins functions support wildcard matches by - // specifying empty strings as parameters, while searchLogins requires - // omitting the property entirely. - let hostname = ("hostname" in aQuery) ? aQuery.hostname : ""; - let formSubmitURL = ("formSubmitURL" in aQuery) ? aQuery.formSubmitURL : ""; - let httpRealm = ("httpRealm" in aQuery) ? aQuery.httpRealm : ""; - - // Test findLogins. - let outCount = {}; - let logins = Services.logins.findLogins(outCount, hostname, formSubmitURL, - httpRealm); - do_check_eq(outCount.value, expectedLogins.length); - LoginTestUtils.assertLoginListsEqual(logins, expectedLogins); - - // Test countLogins. - let count = Services.logins.countLogins(hostname, formSubmitURL, httpRealm); - do_check_eq(count, expectedLogins.length); - - // Test searchLogins. - checkSearchLogins(aQuery, aExpectedCount); -} - -// Tests - -/** - * Prepare data for the following tests. - */ -add_task(function test_initialize() -{ - for (let login of TestData.loginList()) { - Services.logins.addLogin(login); - } -}); - -/** - * Tests findLogins, searchLogins, and countLogins with basic queries. - */ -add_task(function test_search_all_basic() -{ - // Find all logins, using no filters in the search functions. - checkAllSearches({}, 23); - - // Find all form logins, then all authentication logins. - checkAllSearches({ httpRealm: null }, 14); - checkAllSearches({ formSubmitURL: null }, 9); - - // Find all form logins on one host, then all authentication logins. - checkAllSearches({ hostname: "http://www4.example.com", - httpRealm: null }, 3); - checkAllSearches({ hostname: "http://www2.example.org", - formSubmitURL: null }, 2); - - // Verify that scheme and subdomain are distinct in the hostname. - checkAllSearches({ hostname: "http://www.example.com" }, 1); - checkAllSearches({ hostname: "https://www.example.com" }, 1); - checkAllSearches({ hostname: "https://example.com" }, 1); - checkAllSearches({ hostname: "http://www3.example.com" }, 3); - - // Verify that scheme and subdomain are distinct in formSubmitURL. - checkAllSearches({ formSubmitURL: "http://www.example.com" }, 2); - checkAllSearches({ formSubmitURL: "https://www.example.com" }, 2); - checkAllSearches({ formSubmitURL: "http://example.com" }, 1); - - // Find by formSubmitURL on a single host. - checkAllSearches({ hostname: "http://www3.example.com", - formSubmitURL: "http://www.example.com" }, 1); - checkAllSearches({ hostname: "http://www3.example.com", - formSubmitURL: "https://www.example.com" }, 1); - checkAllSearches({ hostname: "http://www3.example.com", - formSubmitURL: "http://example.com" }, 1); - - // Find by httpRealm on all hosts. - checkAllSearches({ httpRealm: "The HTTP Realm" }, 3); - checkAllSearches({ httpRealm: "ftp://ftp.example.org" }, 1); - checkAllSearches({ httpRealm: "The HTTP Realm Other" }, 2); - - // Find by httpRealm on a single host. - checkAllSearches({ hostname: "http://example.net", - httpRealm: "The HTTP Realm" }, 1); - checkAllSearches({ hostname: "http://example.net", - httpRealm: "The HTTP Realm Other" }, 1); - checkAllSearches({ hostname: "ftp://example.net", - httpRealm: "ftp://example.net" }, 1); -}); - -/** - * Tests searchLogins with advanced queries. - */ -add_task(function test_searchLogins() -{ - checkSearchLogins({ usernameField: "form_field_username" }, 12); - checkSearchLogins({ passwordField: "form_field_password" }, 13); - - // Find all logins with an empty usernameField, including for authentication. - checkSearchLogins({ usernameField: "" }, 11); - - // Find form logins with an empty usernameField. - checkSearchLogins({ httpRealm: null, - usernameField: "" }, 2); - - // Find logins with an empty usernameField on one host. - checkSearchLogins({ hostname: "http://www6.example.com", - usernameField: "" }, 1); -}); - -/** - * Tests searchLogins with invalid arguments. - */ -add_task(function test_searchLogins_invalid() -{ - Assert.throws(() => Services.logins.searchLogins({}, - newPropertyBag({ username: "value" })), - /Unexpected field/); -}); - -/** - * Tests that matches are case-sensitive, compare the full field value, and are - * strict when interpreting the prePath of URIs. - */ -add_task(function test_search_all_full_case_sensitive() -{ - checkAllSearches({ hostname: "http://www.example.com" }, 1); - checkAllSearches({ hostname: "http://www.example.com/" }, 0); - checkAllSearches({ hostname: "example.com" }, 0); - - checkAllSearches({ formSubmitURL: "http://www.example.com" }, 2); - checkAllSearches({ formSubmitURL: "http://www.example.com/" }, 0); - checkAllSearches({ formSubmitURL: "http://" }, 0); - checkAllSearches({ formSubmitURL: "example.com" }, 0); - - checkAllSearches({ httpRealm: "The HTTP Realm" }, 3); - checkAllSearches({ httpRealm: "The http Realm" }, 0); - checkAllSearches({ httpRealm: "The HTTP" }, 0); - checkAllSearches({ httpRealm: "Realm" }, 0); -}); - -/** - * Tests findLogins, searchLogins, and countLogins with queries that should - * return no values. - */ -add_task(function test_search_all_empty() -{ - checkAllSearches({ hostname: "http://nonexistent.example.com" }, 0); - checkAllSearches({ formSubmitURL: "http://www.example.com", - httpRealm: "The HTTP Realm" }, 0); - - checkSearchLogins({ hostname: "" }, 0); - checkSearchLogins({ id: "1000" }, 0); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_maybeImportLogin.js b/toolkit/components/passwordmgr/test/unit/test_maybeImportLogin.js deleted file mode 100644 index 19175df59..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_maybeImportLogin.js +++ /dev/null @@ -1,169 +0,0 @@ -"use strict"; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/LoginHelper.jsm"); - -const HOST1 = "https://www.example.com/"; -const HOST2 = "https://www.mozilla.org/"; - -const USER1 = "myuser"; -const USER2 = "anotheruser"; - -const PASS1 = "mypass"; -const PASS2 = "anotherpass"; -const PASS3 = "yetanotherpass"; - -add_task(function test_new_logins() { - let importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - }); - Assert.ok(importedLogin, "Return value should indicate imported login."); - let matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should be 1 login for ${HOST1}`); - - importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST2, - formSubmitURL: HOST2, - }); - - Assert.ok(importedLogin, "Return value should indicate another imported login."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should still be 1 login for ${HOST1}`); - - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST2}); - Assert.equal(matchingLogins.length, 1, `There should also be 1 login for ${HOST2}`); - Assert.equal(Services.logins.getAllLogins().length, 2, "There should be 2 logins in total"); - Services.logins.removeAllLogins(); -}); - -add_task(function test_duplicate_logins() { - let importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - }); - Assert.ok(importedLogin, "Return value should indicate imported login."); - let matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should be 1 login for ${HOST1}`); - - importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - }); - Assert.ok(!importedLogin, "Return value should indicate no new login was imported."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should still be 1 login for ${HOST1}`); - Services.logins.removeAllLogins(); -}); - -add_task(function test_different_passwords() { - let importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - timeCreated: new Date(Date.now() - 1000), - }); - Assert.ok(importedLogin, "Return value should indicate imported login."); - let matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should be 1 login for ${HOST1}`); - - // This item will be newer, so its password should take precedence. - importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS2, - hostname: HOST1, - formSubmitURL: HOST1, - timeCreated: new Date(), - }); - Assert.ok(!importedLogin, "Return value should not indicate imported login (as we updated an existing one)."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should still be 1 login for ${HOST1}`); - Assert.equal(matchingLogins[0].password, PASS2, "We should have updated the password for this login."); - - // Now try to update with an older password: - importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS3, - hostname: HOST1, - formSubmitURL: HOST1, - timeCreated: new Date(Date.now() - 1000000), - }); - Assert.ok(!importedLogin, "Return value should not indicate imported login (as we didn't update anything)."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should still be 1 login for ${HOST1}`); - Assert.equal(matchingLogins[0].password, PASS2, "We should NOT have updated the password for this login."); - - Services.logins.removeAllLogins(); -}); - -add_task(function test_different_usernames() { - let importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - }); - Assert.ok(importedLogin, "Return value should indicate imported login."); - let matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should be 1 login for ${HOST1}`); - - importedLogin = LoginHelper.maybeImportLogin({ - username: USER2, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - }); - Assert.ok(importedLogin, "Return value should indicate another imported login."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 2, `There should now be 2 logins for ${HOST1}`); - - Services.logins.removeAllLogins(); -}); - -add_task(function test_different_targets() { - let importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - formSubmitURL: HOST1, - }); - Assert.ok(importedLogin, "Return value should indicate imported login."); - let matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should be 1 login for ${HOST1}`); - - // Not passing either a formSubmitURL or a httpRealm should be treated as - // the same as the previous login - importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - }); - Assert.ok(!importedLogin, "Return value should NOT indicate imported login " + - "(because a missing formSubmitURL and httpRealm should be duped to the existing login)."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 1, `There should still be 1 login for ${HOST1}`); - Assert.equal(matchingLogins[0].formSubmitURL, HOST1, "The form submission URL should have been kept."); - - importedLogin = LoginHelper.maybeImportLogin({ - username: USER1, - password: PASS1, - hostname: HOST1, - httpRealm: HOST1, - }); - Assert.ok(importedLogin, "Return value should indicate another imported login " + - "as an httpRealm login shouldn't be duped."); - matchingLogins = LoginHelper.searchLoginsWithObject({hostname: HOST1}); - Assert.equal(matchingLogins.length, 2, `There should now be 2 logins for ${HOST1}`); - - Services.logins.removeAllLogins(); -}); - diff --git a/toolkit/components/passwordmgr/test/unit/test_module_LoginImport.js b/toolkit/components/passwordmgr/test/unit/test_module_LoginImport.js deleted file mode 100644 index b8793e1bd..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_module_LoginImport.js +++ /dev/null @@ -1,243 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the LoginImport object. - */ - -"use strict"; - -// Globals - -Cu.import("resource://gre/modules/Task.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper", - "resource://gre/modules/LoginHelper.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "LoginImport", - "resource://gre/modules/LoginImport.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "LoginStore", - "resource://gre/modules/LoginStore.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Sqlite", - "resource://gre/modules/Sqlite.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "gLoginManagerCrypto", - "@mozilla.org/login-manager/crypto/SDR;1", - "nsILoginManagerCrypto"); -XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator", - "@mozilla.org/uuid-generator;1", - "nsIUUIDGenerator"); - -/** - * Creates empty login data tables in the given SQLite connection, resembling - * the most recent schema version (excluding indices). - */ -function promiseCreateDatabaseSchema(aConnection) -{ - return Task.spawn(function* () { - yield aConnection.setSchemaVersion(5); - yield aConnection.execute("CREATE TABLE moz_logins (" + - "id INTEGER PRIMARY KEY," + - "hostname TEXT NOT NULL," + - "httpRealm TEXT," + - "formSubmitURL TEXT," + - "usernameField TEXT NOT NULL," + - "passwordField TEXT NOT NULL," + - "encryptedUsername TEXT NOT NULL," + - "encryptedPassword TEXT NOT NULL," + - "guid TEXT," + - "encType INTEGER," + - "timeCreated INTEGER," + - "timeLastUsed INTEGER," + - "timePasswordChanged INTEGER," + - "timesUsed INTEGER)"); - yield aConnection.execute("CREATE TABLE moz_disabledHosts (" + - "id INTEGER PRIMARY KEY," + - "hostname TEXT UNIQUE)"); - yield aConnection.execute("CREATE TABLE moz_deleted_logins (" + - "id INTEGER PRIMARY KEY," + - "guid TEXT," + - "timeDeleted INTEGER)"); - }); -} - -/** - * Inserts a new entry in the database resembling the given nsILoginInfo object. - */ -function promiseInsertLoginInfo(aConnection, aLoginInfo) -{ - aLoginInfo.QueryInterface(Ci.nsILoginMetaInfo); - - // We can't use the aLoginInfo object directly in the execute statement - // because the bind code in Sqlite.jsm doesn't allow objects with extra - // properties beyond those being binded. So we might as well use an array as - // it is simpler. - let values = [ - aLoginInfo.hostname, - aLoginInfo.httpRealm, - aLoginInfo.formSubmitURL, - aLoginInfo.usernameField, - aLoginInfo.passwordField, - gLoginManagerCrypto.encrypt(aLoginInfo.username), - gLoginManagerCrypto.encrypt(aLoginInfo.password), - aLoginInfo.guid, - aLoginInfo.encType, - aLoginInfo.timeCreated, - aLoginInfo.timeLastUsed, - aLoginInfo.timePasswordChanged, - aLoginInfo.timesUsed, - ]; - - return aConnection.execute("INSERT INTO moz_logins (hostname, " + - "httpRealm, formSubmitURL, usernameField, " + - "passwordField, encryptedUsername, " + - "encryptedPassword, guid, encType, timeCreated, " + - "timeLastUsed, timePasswordChanged, timesUsed) " + - "VALUES (?" + ",?".repeat(12) + ")", values); -} - -/** - * Inserts a new disabled host entry in the database. - */ -function promiseInsertDisabledHost(aConnection, aHostname) -{ - return aConnection.execute("INSERT INTO moz_disabledHosts (hostname) " + - "VALUES (?)", [aHostname]); -} - -// Tests - -/** - * Imports login data from a SQLite file constructed using the test data. - */ -add_task(function* test_import() -{ - let store = new LoginStore(getTempFile("test-import.json").path); - let loginsSqlite = getTempFile("test-logins.sqlite").path; - - // Prepare the logins to be imported, including the nsILoginMetaInfo data. - let loginList = TestData.loginList(); - for (let loginInfo of loginList) { - loginInfo.QueryInterface(Ci.nsILoginMetaInfo); - loginInfo.guid = gUUIDGenerator.generateUUID().toString(); - loginInfo.timeCreated = Date.now(); - loginInfo.timeLastUsed = Date.now(); - loginInfo.timePasswordChanged = Date.now(); - loginInfo.timesUsed = 1; - } - - // Create and populate the SQLite database first. - let connection = yield Sqlite.openConnection({ path: loginsSqlite }); - try { - yield promiseCreateDatabaseSchema(connection); - for (let loginInfo of loginList) { - yield promiseInsertLoginInfo(connection, loginInfo); - } - yield promiseInsertDisabledHost(connection, "http://www.example.com"); - yield promiseInsertDisabledHost(connection, "https://www.example.org"); - } finally { - yield connection.close(); - } - - // The "load" method must be called before importing data. - yield store.load(); - yield new LoginImport(store, loginsSqlite).import(); - - // Verify that every login in the test data has a matching imported row. - do_check_eq(loginList.length, store.data.logins.length); - do_check_true(loginList.every(function (loginInfo) { - return store.data.logins.some(function (loginDataItem) { - let username = gLoginManagerCrypto.decrypt(loginDataItem.encryptedUsername); - let password = gLoginManagerCrypto.decrypt(loginDataItem.encryptedPassword); - return loginDataItem.hostname == loginInfo.hostname && - loginDataItem.httpRealm == loginInfo.httpRealm && - loginDataItem.formSubmitURL == loginInfo.formSubmitURL && - loginDataItem.usernameField == loginInfo.usernameField && - loginDataItem.passwordField == loginInfo.passwordField && - username == loginInfo.username && - password == loginInfo.password && - loginDataItem.guid == loginInfo.guid && - loginDataItem.encType == loginInfo.encType && - loginDataItem.timeCreated == loginInfo.timeCreated && - loginDataItem.timeLastUsed == loginInfo.timeLastUsed && - loginDataItem.timePasswordChanged == loginInfo.timePasswordChanged && - loginDataItem.timesUsed == loginInfo.timesUsed; - }); - })); - - // Verify that disabled hosts have been imported. - do_check_eq(store.data.disabledHosts.length, 2); - do_check_true(store.data.disabledHosts.indexOf("http://www.example.com") != -1); - do_check_true(store.data.disabledHosts.indexOf("https://www.example.org") != -1); -}); - -/** - * Tests imports of NULL values due to a downgraded database. - */ -add_task(function* test_import_downgraded() -{ - let store = new LoginStore(getTempFile("test-import-downgraded.json").path); - let loginsSqlite = getTempFile("test-logins-downgraded.sqlite").path; - - // Create and populate the SQLite database first. - let connection = yield Sqlite.openConnection({ path: loginsSqlite }); - try { - yield promiseCreateDatabaseSchema(connection); - yield connection.setSchemaVersion(3); - yield promiseInsertLoginInfo(connection, TestData.formLogin({ - guid: gUUIDGenerator.generateUUID().toString(), - timeCreated: null, - timeLastUsed: null, - timePasswordChanged: null, - timesUsed: 0, - })); - } finally { - yield connection.close(); - } - - // The "load" method must be called before importing data. - yield store.load(); - yield new LoginImport(store, loginsSqlite).import(); - - // Verify that the missing metadata was generated correctly. - let loginItem = store.data.logins[0]; - let creationTime = loginItem.timeCreated; - LoginTestUtils.assertTimeIsAboutNow(creationTime); - do_check_eq(loginItem.timeLastUsed, creationTime); - do_check_eq(loginItem.timePasswordChanged, creationTime); - do_check_eq(loginItem.timesUsed, 1); -}); - -/** - * Verifies that importing from a SQLite file with database version 2 fails. - */ -add_task(function* test_import_v2() -{ - let store = new LoginStore(getTempFile("test-import-v2.json").path); - let loginsSqlite = do_get_file("data/signons-v2.sqlite").path; - - // The "load" method must be called before importing data. - yield store.load(); - try { - yield new LoginImport(store, loginsSqlite).import(); - do_throw("The operation should have failed."); - } catch (ex) { } -}); - -/** - * Imports login data from a SQLite file, with database version 3. - */ -add_task(function* test_import_v3() -{ - let store = new LoginStore(getTempFile("test-import-v3.json").path); - let loginsSqlite = do_get_file("data/signons-v3.sqlite").path; - - // The "load" method must be called before importing data. - yield store.load(); - yield new LoginImport(store, loginsSqlite).import(); - - // We only execute basic integrity checks. - do_check_eq(store.data.logins[0].usernameField, "u1"); - do_check_eq(store.data.disabledHosts.length, 0); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_module_LoginStore.js b/toolkit/components/passwordmgr/test/unit/test_module_LoginStore.js deleted file mode 100644 index 335eb601b..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_module_LoginStore.js +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the LoginStore object. - */ - -"use strict"; - -// Globals - -XPCOMUtils.defineLazyModuleGetter(this, "LoginStore", - "resource://gre/modules/LoginStore.jsm"); - -const TEST_STORE_FILE_NAME = "test-logins.json"; - -// Tests - -/** - * Saves login data to a file, then reloads it. - */ -add_task(function* test_save_reload() -{ - let storeForSave = new LoginStore(getTempFile(TEST_STORE_FILE_NAME).path); - - // The "load" method must be called before preparing the data to be saved. - yield storeForSave.load(); - - let rawLoginData = { - id: storeForSave.data.nextId++, - hostname: "http://www.example.com", - httpRealm: null, - formSubmitURL: "http://www.example.com/submit-url", - usernameField: "field_" + String.fromCharCode(533, 537, 7570, 345), - passwordField: "field_" + String.fromCharCode(421, 259, 349, 537), - encryptedUsername: "(test)", - encryptedPassword: "(test)", - guid: "(test)", - encType: Ci.nsILoginManagerCrypto.ENCTYPE_SDR, - timeCreated: Date.now(), - timeLastUsed: Date.now(), - timePasswordChanged: Date.now(), - timesUsed: 1, - }; - storeForSave.data.logins.push(rawLoginData); - - storeForSave.data.disabledHosts.push("http://www.example.org"); - - yield storeForSave._save(); - - // Test the asynchronous initialization path. - let storeForLoad = new LoginStore(storeForSave.path); - yield storeForLoad.load(); - - do_check_eq(storeForLoad.data.logins.length, 1); - do_check_matches(storeForLoad.data.logins[0], rawLoginData); - do_check_eq(storeForLoad.data.disabledHosts.length, 1); - do_check_eq(storeForLoad.data.disabledHosts[0], "http://www.example.org"); - - // Test the synchronous initialization path. - storeForLoad = new LoginStore(storeForSave.path); - storeForLoad.ensureDataReady(); - - do_check_eq(storeForLoad.data.logins.length, 1); - do_check_matches(storeForLoad.data.logins[0], rawLoginData); - do_check_eq(storeForLoad.data.disabledHosts.length, 1); - do_check_eq(storeForLoad.data.disabledHosts[0], "http://www.example.org"); -}); - -/** - * Checks that loading from a missing file results in empty arrays. - */ -add_task(function* test_load_empty() -{ - let store = new LoginStore(getTempFile(TEST_STORE_FILE_NAME).path); - - do_check_false(yield OS.File.exists(store.path)); - - yield store.load(); - - do_check_false(yield OS.File.exists(store.path)); - - do_check_eq(store.data.logins.length, 0); - do_check_eq(store.data.disabledHosts.length, 0); -}); - -/** - * Checks that saving empty data still overwrites any existing file. - */ -add_task(function* test_save_empty() -{ - let store = new LoginStore(getTempFile(TEST_STORE_FILE_NAME).path); - - yield store.load(); - - let createdFile = yield OS.File.open(store.path, { create: true }); - yield createdFile.close(); - - yield store._save(); - - do_check_true(yield OS.File.exists(store.path)); -}); - -/** - * Loads data from a string in a predefined format. The purpose of this test is - * to verify that the JSON format used in previous versions can be loaded. - */ -add_task(function* test_load_string_predefined() -{ - let store = new LoginStore(getTempFile(TEST_STORE_FILE_NAME).path); - - let string = "{\"logins\":[{" + - "\"id\":1," + - "\"hostname\":\"http://www.example.com\"," + - "\"httpRealm\":null," + - "\"formSubmitURL\":\"http://www.example.com/submit-url\"," + - "\"usernameField\":\"usernameField\"," + - "\"passwordField\":\"passwordField\"," + - "\"encryptedUsername\":\"(test)\"," + - "\"encryptedPassword\":\"(test)\"," + - "\"guid\":\"(test)\"," + - "\"encType\":1," + - "\"timeCreated\":1262304000000," + - "\"timeLastUsed\":1262390400000," + - "\"timePasswordChanged\":1262476800000," + - "\"timesUsed\":1}],\"disabledHosts\":[" + - "\"http://www.example.org\"]}"; - - yield OS.File.writeAtomic(store.path, - new TextEncoder().encode(string), - { tmpPath: store.path + ".tmp" }); - - yield store.load(); - - do_check_eq(store.data.logins.length, 1); - do_check_matches(store.data.logins[0], { - id: 1, - hostname: "http://www.example.com", - httpRealm: null, - formSubmitURL: "http://www.example.com/submit-url", - usernameField: "usernameField", - passwordField: "passwordField", - encryptedUsername: "(test)", - encryptedPassword: "(test)", - guid: "(test)", - encType: Ci.nsILoginManagerCrypto.ENCTYPE_SDR, - timeCreated: 1262304000000, - timeLastUsed: 1262390400000, - timePasswordChanged: 1262476800000, - timesUsed: 1, - }); - - do_check_eq(store.data.disabledHosts.length, 1); - do_check_eq(store.data.disabledHosts[0], "http://www.example.org"); -}); - -/** - * Loads login data from a malformed JSON string. - */ -add_task(function* test_load_string_malformed() -{ - let store = new LoginStore(getTempFile(TEST_STORE_FILE_NAME).path); - - let string = "{\"logins\":[{\"hostname\":\"http://www.example.com\"," + - "\"id\":1,"; - - yield OS.File.writeAtomic(store.path, new TextEncoder().encode(string), - { tmpPath: store.path + ".tmp" }); - - yield store.load(); - - // A backup file should have been created. - do_check_true(yield OS.File.exists(store.path + ".corrupt")); - yield OS.File.remove(store.path + ".corrupt"); - - // The store should be ready to accept new data. - do_check_eq(store.data.logins.length, 0); - do_check_eq(store.data.disabledHosts.length, 0); -}); - -/** - * Loads login data from a malformed JSON string, using the synchronous - * initialization path. - */ -add_task(function* test_load_string_malformed_sync() -{ - let store = new LoginStore(getTempFile(TEST_STORE_FILE_NAME).path); - - let string = "{\"logins\":[{\"hostname\":\"http://www.example.com\"," + - "\"id\":1,"; - - yield OS.File.writeAtomic(store.path, new TextEncoder().encode(string), - { tmpPath: store.path + ".tmp" }); - - store.ensureDataReady(); - - // A backup file should have been created. - do_check_true(yield OS.File.exists(store.path + ".corrupt")); - yield OS.File.remove(store.path + ".corrupt"); - - // The store should be ready to accept new data. - do_check_eq(store.data.logins.length, 0); - do_check_eq(store.data.disabledHosts.length, 0); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_notifications.js b/toolkit/components/passwordmgr/test/unit/test_notifications.js deleted file mode 100644 index 41caa2c1b..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_notifications.js +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Tests notifications dispatched when modifying stored logins. - */ - -var expectedNotification; -var expectedData; - -var TestObserver = { - QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]), - - observe : function (subject, topic, data) { - do_check_eq(topic, "passwordmgr-storage-changed"); - do_check_eq(data, expectedNotification); - - switch (data) { - case "addLogin": - do_check_true(subject instanceof Ci.nsILoginInfo); - do_check_true(subject instanceof Ci.nsILoginMetaInfo); - do_check_true(expectedData.equals(subject)); // nsILoginInfo.equals() - break; - case "modifyLogin": - do_check_true(subject instanceof Ci.nsIArray); - do_check_eq(subject.length, 2); - var oldLogin = subject.queryElementAt(0, Ci.nsILoginInfo); - var newLogin = subject.queryElementAt(1, Ci.nsILoginInfo); - do_check_true(expectedData[0].equals(oldLogin)); // nsILoginInfo.equals() - do_check_true(expectedData[1].equals(newLogin)); - break; - case "removeLogin": - do_check_true(subject instanceof Ci.nsILoginInfo); - do_check_true(subject instanceof Ci.nsILoginMetaInfo); - do_check_true(expectedData.equals(subject)); // nsILoginInfo.equals() - break; - case "removeAllLogins": - do_check_eq(subject, null); - break; - case "hostSavingEnabled": - case "hostSavingDisabled": - do_check_true(subject instanceof Ci.nsISupportsString); - do_check_eq(subject.data, expectedData); - break; - default: - do_throw("Unhandled notification: " + data + " / " + topic); - } - - expectedNotification = null; // ensure a duplicate is flagged as unexpected. - expectedData = null; - } -}; - -add_task(function test_notifications() -{ - -try { - -var testnum = 0; -var testdesc = "Setup of nsLoginInfo test-users"; - -var testuser1 = new LoginInfo("http://testhost1", "", null, - "dummydude", "itsasecret", "put_user_here", "put_pw_here"); - -var testuser2 = new LoginInfo("http://testhost2", "", null, - "dummydude2", "itsasecret2", "put_user2_here", "put_pw2_here"); - -Services.obs.addObserver(TestObserver, "passwordmgr-storage-changed", false); - - -/* ========== 1 ========== */ -testnum = 1; -testdesc = "Initial connection to storage module"; - -/* ========== 2 ========== */ -testnum++; -testdesc = "addLogin"; - -expectedNotification = "addLogin"; -expectedData = testuser1; -Services.logins.addLogin(testuser1); -LoginTestUtils.checkLogins([testuser1]); -do_check_eq(expectedNotification, null); // check that observer got a notification - -/* ========== 3 ========== */ -testnum++; -testdesc = "modifyLogin"; - -expectedNotification = "modifyLogin"; -expectedData = [testuser1, testuser2]; -Services.logins.modifyLogin(testuser1, testuser2); -do_check_eq(expectedNotification, null); -LoginTestUtils.checkLogins([testuser2]); - -/* ========== 4 ========== */ -testnum++; -testdesc = "removeLogin"; - -expectedNotification = "removeLogin"; -expectedData = testuser2; -Services.logins.removeLogin(testuser2); -do_check_eq(expectedNotification, null); -LoginTestUtils.checkLogins([]); - -/* ========== 5 ========== */ -testnum++; -testdesc = "removeAllLogins"; - -expectedNotification = "removeAllLogins"; -expectedData = null; -Services.logins.removeAllLogins(); -do_check_eq(expectedNotification, null); -LoginTestUtils.checkLogins([]); - -/* ========== 6 ========== */ -testnum++; -testdesc = "removeAllLogins (again)"; - -expectedNotification = "removeAllLogins"; -expectedData = null; -Services.logins.removeAllLogins(); -do_check_eq(expectedNotification, null); -LoginTestUtils.checkLogins([]); - -/* ========== 7 ========== */ -testnum++; -testdesc = "setLoginSavingEnabled / false"; - -expectedNotification = "hostSavingDisabled"; -expectedData = "http://site.com"; -Services.logins.setLoginSavingEnabled("http://site.com", false); -do_check_eq(expectedNotification, null); -LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - ["http://site.com"]); - -/* ========== 8 ========== */ -testnum++; -testdesc = "setLoginSavingEnabled / false (again)"; - -expectedNotification = "hostSavingDisabled"; -expectedData = "http://site.com"; -Services.logins.setLoginSavingEnabled("http://site.com", false); -do_check_eq(expectedNotification, null); -LoginTestUtils.assertDisabledHostsEqual(Services.logins.getAllDisabledHosts(), - ["http://site.com"]); - -/* ========== 9 ========== */ -testnum++; -testdesc = "setLoginSavingEnabled / true"; - -expectedNotification = "hostSavingEnabled"; -expectedData = "http://site.com"; -Services.logins.setLoginSavingEnabled("http://site.com", true); -do_check_eq(expectedNotification, null); -LoginTestUtils.checkLogins([]); - -/* ========== 10 ========== */ -testnum++; -testdesc = "setLoginSavingEnabled / true (again)"; - -expectedNotification = "hostSavingEnabled"; -expectedData = "http://site.com"; -Services.logins.setLoginSavingEnabled("http://site.com", true); -do_check_eq(expectedNotification, null); -LoginTestUtils.checkLogins([]); - -Services.obs.removeObserver(TestObserver, "passwordmgr-storage-changed"); - -LoginTestUtils.clearData(); - -} catch (e) { - throw new Error("FAILED in test #" + testnum + " -- " + testdesc + ": " + e); -} - -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_recipes_add.js b/toolkit/components/passwordmgr/test/unit/test_recipes_add.js deleted file mode 100644 index ef5086c3b..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_recipes_add.js +++ /dev/null @@ -1,177 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests adding and retrieving LoginRecipes in the parent process. - */ - -"use strict"; - -add_task(function* test_init() { - let parent = new LoginRecipesParent({ defaults: null }); - let initPromise1 = parent.initializationPromise; - let initPromise2 = parent.initializationPromise; - Assert.strictEqual(initPromise1, initPromise2, "Check that the same promise is returned"); - - let recipesParent = yield initPromise1; - Assert.ok(recipesParent instanceof LoginRecipesParent, "Check init return value"); - Assert.strictEqual(recipesParent._recipesByHost.size, 0, "Initially 0 recipes"); -}); - -add_task(function* test_get_missing_host() { - let recipesParent = yield RecipeHelpers.initNewParent(); - let exampleRecipes = recipesParent.getRecipesForHost("example.invalid"); - Assert.strictEqual(exampleRecipes.size, 0, "Check recipe count for example.invalid"); - -}); - -add_task(function* test_add_get_simple_host() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.strictEqual(recipesParent._recipesByHost.size, 0, "Initially 0 recipes"); - recipesParent.add({ - hosts: ["example.com"], - }); - Assert.strictEqual(recipesParent._recipesByHost.size, 1, - "Check number of hosts after the addition"); - - let exampleRecipes = recipesParent.getRecipesForHost("example.com"); - Assert.strictEqual(exampleRecipes.size, 1, "Check recipe count for example.com"); - let recipe = [...exampleRecipes][0]; - Assert.strictEqual(typeof(recipe), "object", "Check recipe type"); - Assert.strictEqual(recipe.hosts.length, 1, "Check that one host is present"); - Assert.strictEqual(recipe.hosts[0], "example.com", "Check the one host"); -}); - -add_task(function* test_add_get_non_standard_port_host() { - let recipesParent = yield RecipeHelpers.initNewParent(); - recipesParent.add({ - hosts: ["example.com:8080"], - }); - Assert.strictEqual(recipesParent._recipesByHost.size, 1, - "Check number of hosts after the addition"); - - let exampleRecipes = recipesParent.getRecipesForHost("example.com:8080"); - Assert.strictEqual(exampleRecipes.size, 1, "Check recipe count for example.com:8080"); - let recipe = [...exampleRecipes][0]; - Assert.strictEqual(typeof(recipe), "object", "Check recipe type"); - Assert.strictEqual(recipe.hosts.length, 1, "Check that one host is present"); - Assert.strictEqual(recipe.hosts[0], "example.com:8080", "Check the one host"); -}); - -add_task(function* test_add_multiple_hosts() { - let recipesParent = yield RecipeHelpers.initNewParent(); - recipesParent.add({ - hosts: ["example.com", "foo.invalid"], - }); - Assert.strictEqual(recipesParent._recipesByHost.size, 2, - "Check number of hosts after the addition"); - - let exampleRecipes = recipesParent.getRecipesForHost("example.com"); - Assert.strictEqual(exampleRecipes.size, 1, "Check recipe count for example.com"); - let recipe = [...exampleRecipes][0]; - Assert.strictEqual(typeof(recipe), "object", "Check recipe type"); - Assert.strictEqual(recipe.hosts.length, 2, "Check that two hosts are present"); - Assert.strictEqual(recipe.hosts[0], "example.com", "Check the first host"); - Assert.strictEqual(recipe.hosts[1], "foo.invalid", "Check the second host"); - - let fooRecipes = recipesParent.getRecipesForHost("foo.invalid"); - Assert.strictEqual(fooRecipes.size, 1, "Check recipe count for foo.invalid"); - let fooRecipe = [...fooRecipes][0]; - Assert.strictEqual(fooRecipe, recipe, "Check that the recipe is shared"); - Assert.strictEqual(typeof(fooRecipe), "object", "Check recipe type"); - Assert.strictEqual(fooRecipe.hosts.length, 2, "Check that two hosts are present"); - Assert.strictEqual(fooRecipe.hosts[0], "example.com", "Check the first host"); - Assert.strictEqual(fooRecipe.hosts[1], "foo.invalid", "Check the second host"); -}); - -add_task(function* test_add_pathRegex() { - let recipesParent = yield RecipeHelpers.initNewParent(); - recipesParent.add({ - hosts: ["example.com"], - pathRegex: /^\/mypath\//, - }); - Assert.strictEqual(recipesParent._recipesByHost.size, 1, - "Check number of hosts after the addition"); - - let exampleRecipes = recipesParent.getRecipesForHost("example.com"); - Assert.strictEqual(exampleRecipes.size, 1, "Check recipe count for example.com"); - let recipe = [...exampleRecipes][0]; - Assert.strictEqual(typeof(recipe), "object", "Check recipe type"); - Assert.strictEqual(recipe.hosts.length, 1, "Check that one host is present"); - Assert.strictEqual(recipe.hosts[0], "example.com", "Check the one host"); - Assert.strictEqual(recipe.pathRegex.toString(), "/^\\/mypath\\//", "Check the pathRegex"); -}); - -add_task(function* test_add_selectors() { - let recipesParent = yield RecipeHelpers.initNewParent(); - recipesParent.add({ - hosts: ["example.com"], - usernameSelector: "#my-username", - passwordSelector: "#my-form > input.password", - }); - Assert.strictEqual(recipesParent._recipesByHost.size, 1, - "Check number of hosts after the addition"); - - let exampleRecipes = recipesParent.getRecipesForHost("example.com"); - Assert.strictEqual(exampleRecipes.size, 1, "Check recipe count for example.com"); - let recipe = [...exampleRecipes][0]; - Assert.strictEqual(typeof(recipe), "object", "Check recipe type"); - Assert.strictEqual(recipe.hosts.length, 1, "Check that one host is present"); - Assert.strictEqual(recipe.hosts[0], "example.com", "Check the one host"); - Assert.strictEqual(recipe.usernameSelector, "#my-username", "Check the usernameSelector"); - Assert.strictEqual(recipe.passwordSelector, "#my-form > input.password", "Check the passwordSelector"); -}); - -/* Begin checking errors with add */ - -add_task(function* test_add_missing_prop() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({}), /required/, "Some properties are required"); -}); - -add_task(function* test_add_unknown_prop() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({ - unknownProp: true, - }), /supported/, "Unknown properties should cause an error to help with typos"); -}); - -add_task(function* test_add_invalid_hosts() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({ - hosts: 404, - }), /array/, "hosts should be an array"); -}); - -add_task(function* test_add_empty_host_array() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({ - hosts: [], - }), /array/, "hosts should be a non-empty array"); -}); - -add_task(function* test_add_pathRegex_non_regexp() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({ - hosts: ["example.com"], - pathRegex: "foo", - }), /regular expression/, "pathRegex should be a RegExp"); -}); - -add_task(function* test_add_usernameSelector_non_string() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({ - hosts: ["example.com"], - usernameSelector: 404, - }), /string/, "usernameSelector should be a string"); -}); - -add_task(function* test_add_passwordSelector_non_string() { - let recipesParent = yield RecipeHelpers.initNewParent(); - Assert.throws(() => recipesParent.add({ - hosts: ["example.com"], - passwordSelector: 404, - }), /string/, "passwordSelector should be a string"); -}); - -/* End checking errors with add */ diff --git a/toolkit/components/passwordmgr/test/unit/test_recipes_content.js b/toolkit/components/passwordmgr/test/unit/test_recipes_content.js deleted file mode 100644 index 3d3751452..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_recipes_content.js +++ /dev/null @@ -1,39 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Test filtering recipes in LoginRecipesContent. - */ - -"use strict"; - -Cu.importGlobalProperties(["URL"]); - -add_task(function* test_getFieldOverrides() { - let recipes = new Set([ - { // path doesn't match but otherwise good - hosts: ["example.com:8080"], - passwordSelector: "#password", - pathRegex: /^\/$/, - usernameSelector: ".username", - }, - { // match with no field overrides - hosts: ["example.com:8080"], - }, - { // best match (field selectors + path match) - description: "best match", - hosts: ["a.invalid", "example.com:8080", "other.invalid"], - passwordSelector: "#password", - pathRegex: /^\/first\/second\/$/, - usernameSelector: ".username", - }, - ]); - - let form = MockDocument.createTestDocument("http://localhost:8080/first/second/", ""). - forms[0]; - let override = LoginRecipesContent.getFieldOverrides(recipes, form); - Assert.strictEqual(override.description, "best match", - "Check the best field override recipe was returned"); - Assert.strictEqual(override.usernameSelector, ".username", "Check usernameSelector"); - Assert.strictEqual(override.passwordSelector, "#password", "Check passwordSelector"); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_removeLegacySignonFiles.js b/toolkit/components/passwordmgr/test/unit/test_removeLegacySignonFiles.js deleted file mode 100644 index 51a107170..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_removeLegacySignonFiles.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Tests the LoginHelper object. - */ - -"use strict"; - - -Cu.import("resource://gre/modules/Task.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper", - "resource://gre/modules/LoginHelper.jsm"); - - -function* createSignonFile(singon) { - let {file, pref} = singon; - - if (pref) { - Services.prefs.setCharPref(pref, file); - } - - yield OS.File.writeAtomic( - OS.Path.join(OS.Constants.Path.profileDir, file), new Uint8Array(1)); -} - -function* isSignonClear(singon) { - const {file, pref} = singon; - const fileExists = yield OS.File.exists( - OS.Path.join(OS.Constants.Path.profileDir, file)); - - if (pref) { - try { - Services.prefs.getCharPref(pref); - return false; - } catch (e) {} - } - - return !fileExists; -} - -add_task(function* test_remove_lagecy_signonfile() { - // In the last test case, signons3.txt being deleted even when - // it doesn't exist. - const signonsSettings = [[ - { file: "signons.txt" }, - { file: "signons2.txt" }, - { file: "signons3.txt" } - ], [ - { file: "signons.txt", pref: "signon.SignonFileName" }, - { file: "signons2.txt", pref: "signon.SignonFileName2" }, - { file: "signons3.txt", pref: "signon.SignonFileName3" } - ], [ - { file: "signons2.txt" }, - { file: "singons.txt", pref: "signon.SignonFileName" }, - { file: "customized2.txt", pref: "signon.SignonFileName2" }, - { file: "customized3.txt", pref: "signon.SignonFileName3" } - ]]; - - for (let setting of signonsSettings) { - for (let singon of setting) { - yield createSignonFile(singon); - } - - LoginHelper.removeLegacySignonFiles(); - - for (let singon of setting) { - equal(yield isSignonClear(singon), true); - } - } -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_search_schemeUpgrades.js b/toolkit/components/passwordmgr/test/unit/test_search_schemeUpgrades.js deleted file mode 100644 index 3406becff..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_search_schemeUpgrades.js +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Test Services.logins.searchLogins with the `schemeUpgrades` property. - */ - -const HTTP3_ORIGIN = "http://www3.example.com"; -const HTTPS_ORIGIN = "https://www.example.com"; -const HTTP_ORIGIN = "http://www.example.com"; - -/** - * Returns a list of new nsILoginInfo objects that are a subset of the test - * data, built to match the specified query. - * - * @param {Object} aQuery - * Each property and value of this object restricts the search to those - * entries from the test data that match the property exactly. - */ -function buildExpectedLogins(aQuery) { - return TestData.loginList().filter( - entry => Object.keys(aQuery).every(name => { - if (name == "schemeUpgrades") { - return true; - } - if (["hostname", "formSubmitURL"].includes(name)) { - return LoginHelper.isOriginMatching(entry[name], aQuery[name], { - schemeUpgrades: aQuery.schemeUpgrades, - }); - } - return entry[name] === aQuery[name]; - })); -} - -/** - * Tests the searchLogins function. - * - * @param {Object} aQuery - * Each property and value of this object is translated to an entry in - * the nsIPropertyBag parameter of searchLogins. - * @param {Number} aExpectedCount - * Number of logins from the test data that should be found. The actual - * list of logins is obtained using the buildExpectedLogins helper, and - * this value is just used to verify that modifications to the test data - * don't make the current test meaningless. - */ -function checkSearch(aQuery, aExpectedCount) { - do_print("Testing searchLogins for " + JSON.stringify(aQuery)); - - let expectedLogins = buildExpectedLogins(aQuery); - do_check_eq(expectedLogins.length, aExpectedCount); - - let outCount = {}; - let logins = Services.logins.searchLogins(outCount, newPropertyBag(aQuery)); - do_check_eq(outCount.value, expectedLogins.length); - LoginTestUtils.assertLoginListsEqual(logins, expectedLogins); -} - -/** - * Prepare data for the following tests. - */ -add_task(function test_initialize() { - for (let login of TestData.loginList()) { - Services.logins.addLogin(login); - } -}); - -/** - * Tests searchLogins with the `schemeUpgrades` property - */ -add_task(function test_search_schemeUpgrades_hostname() { - // Hostname-only - checkSearch({ - hostname: HTTPS_ORIGIN, - }, 1); - checkSearch({ - hostname: HTTPS_ORIGIN, - schemeUpgrades: false, - }, 1); - checkSearch({ - hostname: HTTPS_ORIGIN, - schemeUpgrades: undefined, - }, 1); - checkSearch({ - hostname: HTTPS_ORIGIN, - schemeUpgrades: true, - }, 2); -}); - -/** - * Same as above but replacing hostname with formSubmitURL. - */ -add_task(function test_search_schemeUpgrades_formSubmitURL() { - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - }, 2); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - schemeUpgrades: false, - }, 2); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - schemeUpgrades: undefined, - }, 2); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - schemeUpgrades: true, - }, 4); -}); - - -add_task(function test_search_schemeUpgrades_hostname_formSubmitURL() { - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - }, 1); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - schemeUpgrades: false, - }, 1); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - schemeUpgrades: undefined, - }, 1); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - schemeUpgrades: true, - }, 2); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - schemeUpgrades: true, - usernameField: "form_field_username", - }, 2); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - passwordField: "form_field_password", - schemeUpgrades: true, - usernameField: "form_field_username", - }, 2); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTPS_ORIGIN, - httpRealm: null, - passwordField: "form_field_password", - schemeUpgrades: true, - usernameField: "form_field_username", - }, 2); -}); - -/** - * HTTP submitting to HTTPS - */ -add_task(function test_http_to_https() { - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTP3_ORIGIN, - httpRealm: null, - schemeUpgrades: false, - }, 1); - checkSearch({ - formSubmitURL: HTTPS_ORIGIN, - hostname: HTTP3_ORIGIN, - httpRealm: null, - schemeUpgrades: true, - }, 2); -}); - -/** - * schemeUpgrades shouldn't cause downgrades - */ -add_task(function test_search_schemeUpgrades_downgrade() { - checkSearch({ - formSubmitURL: HTTP_ORIGIN, - hostname: HTTP_ORIGIN, - }, 1); - do_print("The same number should be found with schemeUpgrades since we're searching for HTTP"); - checkSearch({ - formSubmitURL: HTTP_ORIGIN, - hostname: HTTP_ORIGIN, - schemeUpgrades: true, - }, 1); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_storage.js b/toolkit/components/passwordmgr/test/unit/test_storage.js deleted file mode 100644 index d65516d9b..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_storage.js +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests that the default nsILoginManagerStorage module attached to the Login - * Manager service is able to save and reload nsILoginInfo properties correctly, - * even when they include special characters. - */ - -"use strict"; - -// Globals - -function* reloadAndCheckLoginsGen(aExpectedLogins) -{ - yield LoginTestUtils.reloadData(); - LoginTestUtils.checkLogins(aExpectedLogins); - LoginTestUtils.clearData(); -} - -// Tests - -/** - * Tests addLogin with valid non-ASCII characters. - */ -add_task(function* test_storage_addLogin_nonascii() -{ - let hostname = "http://" + String.fromCharCode(355) + ".example.com"; - - // Store the strings "user" and "pass" using similarly looking glyphs. - let loginInfo = TestData.formLogin({ - hostname: hostname, - formSubmitURL: hostname, - username: String.fromCharCode(533, 537, 7570, 345), - password: String.fromCharCode(421, 259, 349, 537), - usernameField: "field_" + String.fromCharCode(533, 537, 7570, 345), - passwordField: "field_" + String.fromCharCode(421, 259, 349, 537), - }); - Services.logins.addLogin(loginInfo); - yield* reloadAndCheckLoginsGen([loginInfo]); - - // Store the string "test" using similarly looking glyphs. - loginInfo = TestData.authLogin({ - httpRealm: String.fromCharCode(355, 277, 349, 357), - }); - Services.logins.addLogin(loginInfo); - yield* reloadAndCheckLoginsGen([loginInfo]); -}); - -/** - * Tests addLogin with newline characters in the username and password. - */ -add_task(function* test_storage_addLogin_newlines() -{ - let loginInfo = TestData.formLogin({ - username: "user\r\nname", - password: "password\r\n", - }); - Services.logins.addLogin(loginInfo); - yield* reloadAndCheckLoginsGen([loginInfo]); -}); - -/** - * Tests addLogin with a single dot in fields where it is allowed. - * - * These tests exist to verify the legacy "signons.txt" storage format. - */ -add_task(function* test_storage_addLogin_dot() -{ - let loginInfo = TestData.formLogin({ hostname: ".", passwordField: "." }); - Services.logins.addLogin(loginInfo); - yield* reloadAndCheckLoginsGen([loginInfo]); - - loginInfo = TestData.authLogin({ httpRealm: "." }); - Services.logins.addLogin(loginInfo); - yield* reloadAndCheckLoginsGen([loginInfo]); -}); - -/** - * Tests addLogin with parentheses in hostnames. - * - * These tests exist to verify the legacy "signons.txt" storage format. - */ -add_task(function* test_storage_addLogin_parentheses() -{ - let loginList = [ - TestData.authLogin({ httpRealm: "(realm" }), - TestData.authLogin({ httpRealm: "realm)" }), - TestData.authLogin({ httpRealm: "(realm)" }), - TestData.authLogin({ httpRealm: ")realm(" }), - TestData.authLogin({ hostname: "http://parens(.example.com" }), - TestData.authLogin({ hostname: "http://parens).example.com" }), - TestData.authLogin({ hostname: "http://parens(example).example.com" }), - TestData.authLogin({ hostname: "http://parens)example(.example.com" }), - ]; - for (let loginInfo of loginList) { - Services.logins.addLogin(loginInfo); - } - yield* reloadAndCheckLoginsGen(loginList); -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js b/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js deleted file mode 100644 index 8eab6efe5..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js +++ /dev/null @@ -1,507 +0,0 @@ -/* - * This test interfaces directly with the mozStorage password storage module, - * bypassing the normal password manager usage. - */ - - -const ENCTYPE_BASE64 = 0; -const ENCTYPE_SDR = 1; -const PERMISSION_SAVE_LOGINS = "login-saving"; - -// Current schema version used by storage-mozStorage.js. This will need to be -// kept in sync with the version there (or else the tests fail). -const CURRENT_SCHEMA = 6; - -function* copyFile(aLeafName) -{ - yield OS.File.copy(OS.Path.join(do_get_file("data").path, aLeafName), - OS.Path.join(OS.Constants.Path.profileDir, aLeafName)); -} - -function openDB(aLeafName) -{ - var dbFile = new FileUtils.File(OS.Constants.Path.profileDir); - dbFile.append(aLeafName); - - return Services.storage.openDatabase(dbFile); -} - -function deleteFile(pathname, filename) -{ - var file = new FileUtils.File(pathname); - file.append(filename); - - // Suppress failures, this happens in the mozstorage tests on Windows - // because the module may still be holding onto the DB. (We don't - // have a way to explicitly shutdown/GC the module). - try { - if (file.exists()) - file.remove(false); - } catch (e) {} -} - -function reloadStorage(aInputPathName, aInputFileName) -{ - var inputFile = null; - if (aInputFileName) { - inputFile = Cc["@mozilla.org/file/local;1"]. - createInstance(Ci.nsILocalFile); - inputFile.initWithPath(aInputPathName); - inputFile.append(aInputFileName); - } - - let storage = Cc["@mozilla.org/login-manager/storage/mozStorage;1"] - .createInstance(Ci.nsILoginManagerStorage); - storage.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIVariant) - .initWithFile(inputFile); - - return storage; -} - -function checkStorageData(storage, ref_disabledHosts, ref_logins) -{ - LoginTestUtils.assertLoginListsEqual(storage.getAllLogins(), ref_logins); - LoginTestUtils.assertDisabledHostsEqual(getAllDisabledHostsFromPermissionManager(), - ref_disabledHosts); -} - -function getAllDisabledHostsFromPermissionManager() { - let disabledHosts = []; - let enumerator = Services.perms.enumerator; - - while (enumerator.hasMoreElements()) { - let perm = enumerator.getNext(); - if (perm.type == PERMISSION_SAVE_LOGINS && perm.capability == Services.perms.DENY_ACTION) { - disabledHosts.push(perm.principal.URI.prePath); - } - } - - return disabledHosts; -} - -function setLoginSavingEnabled(origin, enabled) { - let uri = Services.io.newURI(origin, null, null); - - if (enabled) { - Services.perms.remove(uri, PERMISSION_SAVE_LOGINS); - } else { - Services.perms.add(uri, PERMISSION_SAVE_LOGINS, Services.perms.DENY_ACTION); - } -} - -add_task(function* test_execute() -{ - -const OUTDIR = OS.Constants.Path.profileDir; - -try { - -var isGUID = /^\{[0-9a-f\d]{8}-[0-9a-f\d]{4}-[0-9a-f\d]{4}-[0-9a-f\d]{4}-[0-9a-f\d]{12}\}$/; -function getGUIDforID(conn, id) { - var stmt = conn.createStatement("SELECT guid from moz_logins WHERE id = " + id); - stmt.executeStep(); - var guid = stmt.getString(0); - stmt.finalize(); - return guid; -} - -function getEncTypeForID(conn, id) { - var stmt = conn.createStatement("SELECT encType from moz_logins WHERE id = " + id); - stmt.executeStep(); - var encType = stmt.row.encType; - stmt.finalize(); - return encType; -} - -function getAllDisabledHostsFromMozStorage(conn) { - let disabledHosts = []; - let stmt = conn.createStatement("SELECT hostname from moz_disabledHosts"); - - while (stmt.executeStep()) { - disabledHosts.push(stmt.row.hostname); - } - - return disabledHosts; -} - -var storage; -var dbConnection; -var testnum = 0; -var testdesc = "Setup of nsLoginInfo test-users"; -var nsLoginInfo = new Components.Constructor( - "@mozilla.org/login-manager/loginInfo;1", - Components.interfaces.nsILoginInfo); -do_check_true(nsLoginInfo != null); - -var testuser1 = new nsLoginInfo; -testuser1.init("http://test.com", "http://test.com", null, - "testuser1", "testpass1", "u1", "p1"); -var testuser1B = new nsLoginInfo; -testuser1B.init("http://test.com", "http://test.com", null, - "testuser1B", "testpass1B", "u1", "p1"); -var testuser2 = new nsLoginInfo; -testuser2.init("http://test.org", "http://test.org", null, - "testuser2", "testpass2", "u2", "p2"); -var testuser3 = new nsLoginInfo; -testuser3.init("http://test.gov", "http://test.gov", null, - "testuser3", "testpass3", "u3", "p3"); -var testuser4 = new nsLoginInfo; -testuser4.init("http://test.gov", "http://test.gov", null, - "testuser1", "testpass2", "u4", "p4"); -var testuser5 = new nsLoginInfo; -testuser5.init("http://test.gov", "http://test.gov", null, - "testuser2", "testpass1", "u5", "p5"); - - -/* ========== 1 ========== */ -testnum++; -testdesc = "Test downgrade from v999 storage"; - -yield* copyFile("signons-v999.sqlite"); -// Verify the schema version in the test file. -dbConnection = openDB("signons-v999.sqlite"); -do_check_eq(999, dbConnection.schemaVersion); -dbConnection.close(); - -storage = reloadStorage(OUTDIR, "signons-v999.sqlite"); -setLoginSavingEnabled("https://disabled.net", false); -checkStorageData(storage, ["https://disabled.net"], [testuser1]); - -// Check to make sure we downgraded the schema version. -dbConnection = openDB("signons-v999.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); -dbConnection.close(); - -deleteFile(OUTDIR, "signons-v999.sqlite"); - -/* ========== 2 ========== */ -testnum++; -testdesc = "Test downgrade from incompat v999 storage"; -// This file has a testuser999/testpass999, but is missing an expected column - -var origFile = OS.Path.join(OUTDIR, "signons-v999-2.sqlite"); -var failFile = OS.Path.join(OUTDIR, "signons-v999-2.sqlite.corrupt"); - -// Make sure we always start clean in a clean state. -yield* copyFile("signons-v999-2.sqlite"); -yield OS.File.remove(failFile); - -Assert.throws(() => reloadStorage(OUTDIR, "signons-v999-2.sqlite"), - /Initialization failed/); - -// Check to ensure the DB file was renamed to .corrupt. -do_check_false(yield OS.File.exists(origFile)); -do_check_true(yield OS.File.exists(failFile)); - -yield OS.File.remove(failFile); - -/* ========== 3 ========== */ -testnum++; -testdesc = "Test upgrade from v1->v2 storage"; - -yield* copyFile("signons-v1.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v1.sqlite"); -do_check_eq(1, dbConnection.schemaVersion); -dbConnection.close(); - -storage = reloadStorage(OUTDIR, "signons-v1.sqlite"); -checkStorageData(storage, ["https://disabled.net"], [testuser1, testuser2]); - -// Check to see that we added a GUIDs to the logins. -dbConnection = openDB("signons-v1.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); -var guid = getGUIDforID(dbConnection, 1); -do_check_true(isGUID.test(guid)); -guid = getGUIDforID(dbConnection, 2); -do_check_true(isGUID.test(guid)); -dbConnection.close(); - -deleteFile(OUTDIR, "signons-v1.sqlite"); - -/* ========== 4 ========== */ -testnum++; -testdesc = "Test upgrade v2->v1 storage"; -// This is the case where a v2 DB has been accessed with v1 code, and now we -// are upgrading it again. Any logins added by the v1 code must be properly -// upgraded. - -yield* copyFile("signons-v1v2.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v1v2.sqlite"); -do_check_eq(1, dbConnection.schemaVersion); -dbConnection.close(); - -storage = reloadStorage(OUTDIR, "signons-v1v2.sqlite"); -checkStorageData(storage, ["https://disabled.net"], [testuser1, testuser2, testuser3]); - -// While we're here, try modifying a login, to ensure that doing so doesn't -// change the existing GUID. -storage.modifyLogin(testuser1, testuser1B); -checkStorageData(storage, ["https://disabled.net"], [testuser1B, testuser2, testuser3]); - -// Check the GUIDs. Logins 1 and 2 should retain their original GUID, login 3 -// should have one created (because it didn't have one previously). -dbConnection = openDB("signons-v1v2.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); -guid = getGUIDforID(dbConnection, 1); -do_check_eq("{655c7358-f1d6-6446-adab-53f98ac5d80f}", guid); -guid = getGUIDforID(dbConnection, 2); -do_check_eq("{13d9bfdc-572a-4d4e-9436-68e9803e84c1}", guid); -guid = getGUIDforID(dbConnection, 3); -do_check_true(isGUID.test(guid)); -dbConnection.close(); - -deleteFile(OUTDIR, "signons-v1v2.sqlite"); - -/* ========== 5 ========== */ -testnum++; -testdesc = "Test upgrade from v2->v3 storage"; - -yield* copyFile("signons-v2.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v2.sqlite"); -do_check_eq(2, dbConnection.schemaVersion); - -storage = reloadStorage(OUTDIR, "signons-v2.sqlite"); - -// Check to see that we added the correct encType to the logins. -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); -var encTypes = [ENCTYPE_BASE64, ENCTYPE_SDR, ENCTYPE_BASE64, ENCTYPE_BASE64]; -for (let i = 0; i < encTypes.length; i++) - do_check_eq(encTypes[i], getEncTypeForID(dbConnection, i + 1)); -dbConnection.close(); - -// There are 4 logins, but 3 will be invalid because we can no longer decrypt -// base64-encoded items. (testuser1/4/5) -checkStorageData(storage, ["https://disabled.net"], - [testuser2]); - -deleteFile(OUTDIR, "signons-v2.sqlite"); - -/* ========== 6 ========== */ -testnum++; -testdesc = "Test upgrade v3->v2 storage"; -// This is the case where a v3 DB has been accessed with v2 code, and now we -// are upgrading it again. Any logins added by the v2 code must be properly -// upgraded. - -yield* copyFile("signons-v2v3.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v2v3.sqlite"); -do_check_eq(2, dbConnection.schemaVersion); -encTypes = [ENCTYPE_BASE64, ENCTYPE_SDR, ENCTYPE_BASE64, ENCTYPE_BASE64, null]; -for (let i = 0; i < encTypes.length; i++) - do_check_eq(encTypes[i], getEncTypeForID(dbConnection, i + 1)); - -// Reload storage, check that the new login now has encType=1, others untouched -storage = reloadStorage(OUTDIR, "signons-v2v3.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); - -encTypes = [ENCTYPE_BASE64, ENCTYPE_SDR, ENCTYPE_BASE64, ENCTYPE_BASE64, ENCTYPE_SDR]; -for (let i = 0; i < encTypes.length; i++) - do_check_eq(encTypes[i], getEncTypeForID(dbConnection, i + 1)); - -// Sanity check that the data gets migrated -// There are 5 logins, but 3 will be invalid because we can no longer decrypt -// base64-encoded items. (testuser1/4/5). We no longer reencrypt with SDR. -checkStorageData(storage, ["https://disabled.net"], [testuser2, testuser3]); -encTypes = [ENCTYPE_BASE64, ENCTYPE_SDR, ENCTYPE_BASE64, ENCTYPE_BASE64, ENCTYPE_SDR]; -for (let i = 0; i < encTypes.length; i++) - do_check_eq(encTypes[i], getEncTypeForID(dbConnection, i + 1)); -dbConnection.close(); - -deleteFile(OUTDIR, "signons-v2v3.sqlite"); - - -/* ========== 7 ========== */ -testnum++; -testdesc = "Test upgrade from v3->v4 storage"; - -yield* copyFile("signons-v3.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v3.sqlite"); -do_check_eq(3, dbConnection.schemaVersion); - -storage = reloadStorage(OUTDIR, "signons-v3.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); - -// Remove old entry from permission manager. -setLoginSavingEnabled("https://disabled.net", true); - -// Check that timestamps and counts were initialized correctly -checkStorageData(storage, [], [testuser1, testuser2]); - -var logins = storage.getAllLogins(); -for (var i = 0; i < 2; i++) { - do_check_true(logins[i] instanceof Ci.nsILoginMetaInfo); - do_check_eq(1, logins[i].timesUsed); - LoginTestUtils.assertTimeIsAboutNow(logins[i].timeCreated); - LoginTestUtils.assertTimeIsAboutNow(logins[i].timeLastUsed); - LoginTestUtils.assertTimeIsAboutNow(logins[i].timePasswordChanged); -} - -/* ========== 8 ========== */ -testnum++; -testdesc = "Test upgrade from v3->v4->v3 storage"; - -yield* copyFile("signons-v3v4.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v3v4.sqlite"); -do_check_eq(3, dbConnection.schemaVersion); - -storage = reloadStorage(OUTDIR, "signons-v3v4.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); - -// testuser1 already has timestamps, testuser2 does not. -checkStorageData(storage, [], [testuser1, testuser2]); - -logins = storage.getAllLogins(); - -var t1, t2; -if (logins[0].username == "testuser1") { - t1 = logins[0]; - t2 = logins[1]; -} else { - t1 = logins[1]; - t2 = logins[0]; -} - -do_check_true(t1 instanceof Ci.nsILoginMetaInfo); -do_check_true(t2 instanceof Ci.nsILoginMetaInfo); - -do_check_eq(9, t1.timesUsed); -do_check_eq(1262049951275, t1.timeCreated); -do_check_eq(1262049951275, t1.timeLastUsed); -do_check_eq(1262049951275, t1.timePasswordChanged); - -do_check_eq(1, t2.timesUsed); -LoginTestUtils.assertTimeIsAboutNow(t2.timeCreated); -LoginTestUtils.assertTimeIsAboutNow(t2.timeLastUsed); -LoginTestUtils.assertTimeIsAboutNow(t2.timePasswordChanged); - - -/* ========== 9 ========== */ -testnum++; -testdesc = "Test upgrade from v4 storage"; - -yield* copyFile("signons-v4.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v4.sqlite"); -do_check_eq(4, dbConnection.schemaVersion); -do_check_false(dbConnection.tableExists("moz_deleted_logins")); - -storage = reloadStorage(OUTDIR, "signons-v4.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); -do_check_true(dbConnection.tableExists("moz_deleted_logins")); - - -/* ========== 10 ========== */ -testnum++; -testdesc = "Test upgrade from v4->v5->v4 storage"; - -yield copyFile("signons-v4v5.sqlite"); -// Sanity check the test file. -dbConnection = openDB("signons-v4v5.sqlite"); -do_check_eq(4, dbConnection.schemaVersion); -do_check_true(dbConnection.tableExists("moz_deleted_logins")); - -storage = reloadStorage(OUTDIR, "signons-v4v5.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); -do_check_true(dbConnection.tableExists("moz_deleted_logins")); - -/* ========== 11 ========== */ -testnum++; -testdesc = "Test upgrade from v5->v6 storage"; - -yield* copyFile("signons-v5v6.sqlite"); - -// Sanity check the test file. -dbConnection = openDB("signons-v5v6.sqlite"); -do_check_eq(5, dbConnection.schemaVersion); -do_check_true(dbConnection.tableExists("moz_disabledHosts")); - -// Initial disabled hosts inside signons-v5v6.sqlite -var disabledHosts = [ - "http://disabled1.example.com", - "http://大.net", - "http://xn--19g.com" -]; - -LoginTestUtils.assertDisabledHostsEqual(disabledHosts, getAllDisabledHostsFromMozStorage(dbConnection)); - -// Reload storage -storage = reloadStorage(OUTDIR, "signons-v5v6.sqlite"); -do_check_eq(CURRENT_SCHEMA, dbConnection.schemaVersion); - -// moz_disabledHosts should now be empty after migration. -LoginTestUtils.assertDisabledHostsEqual([], getAllDisabledHostsFromMozStorage(dbConnection)); - -// Get all the other hosts currently saved in the permission manager. -let hostsInPermissionManager = getAllDisabledHostsFromPermissionManager(); - -// All disabledHosts should have migrated to the permission manager -LoginTestUtils.assertDisabledHostsEqual(disabledHosts, hostsInPermissionManager); - -// Remove all disabled hosts from the permission manager before test ends -for (let host of disabledHosts) { - setLoginSavingEnabled(host, true); -} - -/* ========== 12 ========== */ -testnum++; -testdesc = "Create nsILoginInfo instances for testing with"; - -testuser1 = new nsLoginInfo; -testuser1.init("http://dummyhost.mozilla.org", "", null, - "dummydude", "itsasecret", "put_user_here", "put_pw_here"); - - -/* - * ---------------------- DB Corruption ---------------------- - * Try to initialize with a corrupt database file. This should create a backup - * file, then upon next use create a new database file. - */ - -/* ========== 13 ========== */ -testnum++; -testdesc = "Corrupt database and backup"; - -const filename = "signons-c.sqlite"; -const filepath = OS.Path.join(OS.Constants.Path.profileDir, filename); - -yield OS.File.copy(do_get_file("data/corruptDB.sqlite").path, filepath); - -// will init mozStorage module with corrupt database, init should fail -Assert.throws( - () => reloadStorage(OS.Constants.Path.profileDir, filename), - /Initialization failed/); - -// check that the backup file exists -do_check_true(yield OS.File.exists(filepath + ".corrupt")); - -// check that the original corrupt file has been deleted -do_check_false(yield OS.File.exists(filepath)); - -// initialize the storage module again -storage = reloadStorage(OS.Constants.Path.profileDir, filename); - -// use the storage module again, should work now -storage.addLogin(testuser1); -checkStorageData(storage, [], [testuser1]); - -// check the file exists -var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); -file.initWithPath(OS.Constants.Path.profileDir); -file.append(filename); -do_check_true(file.exists()); - -deleteFile(OS.Constants.Path.profileDir, filename + ".corrupt"); -deleteFile(OS.Constants.Path.profileDir, filename); - -} catch (e) { - throw new Error("FAILED in test #" + testnum + " -- " + testdesc + ": " + e); -} - -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_telemetry.js b/toolkit/components/passwordmgr/test/unit/test_telemetry.js deleted file mode 100644 index 1d8f80226..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_telemetry.js +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests the statistics and other counters reported through telemetry. - */ - -"use strict"; - -// Globals - -const MS_PER_DAY = 24 * 60 * 60 * 1000; - -// To prevent intermittent failures when the test is executed at a time that is -// very close to a day boundary, we make it deterministic by using a static -// reference date for all the time-based statistics. -const gReferenceTimeMs = new Date("2000-01-01T00:00:00").getTime(); - -// Returns a milliseconds value to use with nsILoginMetaInfo properties, falling -// approximately in the middle of the specified number of days before the -// reference time, where zero days indicates a time within the past 24 hours. -var daysBeforeMs = days => gReferenceTimeMs - (days + 0.5) * MS_PER_DAY; - -/** - * Contains metadata that will be attached to test logins in order to verify - * that the statistics collection is working properly. Most properties of the - * logins are initialized to the default test values already. - * - * If you update this data or any of the telemetry histograms it checks, you'll - * probably need to update the expected statistics in the test below. - */ -const StatisticsTestData = [ - { - timeLastUsed: daysBeforeMs(0), - }, - { - timeLastUsed: daysBeforeMs(1), - }, - { - timeLastUsed: daysBeforeMs(7), - formSubmitURL: null, - httpRealm: "The HTTP Realm", - }, - { - username: "", - timeLastUsed: daysBeforeMs(7), - }, - { - username: "", - timeLastUsed: daysBeforeMs(30), - }, - { - username: "", - timeLastUsed: daysBeforeMs(31), - }, - { - timeLastUsed: daysBeforeMs(365), - }, - { - username: "", - timeLastUsed: daysBeforeMs(366), - }, - { - // If the login was saved in the future, it is ignored for statistiscs. - timeLastUsed: daysBeforeMs(-1), - }, - { - timeLastUsed: daysBeforeMs(1000), - }, -]; - -/** - * Triggers the collection of those statistics that are not accumulated each - * time an action is taken, but are a static snapshot of the current state. - */ -function triggerStatisticsCollection() { - Services.obs.notifyObservers(null, "gather-telemetry", "" + gReferenceTimeMs); -} - -/** - * Tests the telemetry histogram with the given ID contains only the specified - * non-zero ranges, expressed in the format { range1: value1, range2: value2 }. - */ -function testHistogram(histogramId, expectedNonZeroRanges) { - let snapshot = Services.telemetry.getHistogramById(histogramId).snapshot(); - - // Compute the actual ranges in the format { range1: value1, range2: value2 }. - let actualNonZeroRanges = {}; - for (let [index, range] of snapshot.ranges.entries()) { - let value = snapshot.counts[index]; - if (value > 0) { - actualNonZeroRanges[range] = value; - } - } - - // These are stringified to visualize the differences between the values. - do_print("Testing histogram: " + histogramId); - do_check_eq(JSON.stringify(actualNonZeroRanges), - JSON.stringify(expectedNonZeroRanges)); -} - -// Tests - -/** - * Enable local telemetry recording for the duration of the tests, and prepare - * the test data that will be used by the following tests. - */ -add_task(function test_initialize() { - let oldCanRecord = Services.telemetry.canRecordExtended; - Services.telemetry.canRecordExtended = true; - do_register_cleanup(function () { - Services.telemetry.canRecordExtended = oldCanRecord; - }); - - let uniqueNumber = 1; - for (let loginModifications of StatisticsTestData) { - loginModifications.hostname = `http://${uniqueNumber++}.example.com`; - Services.logins.addLogin(TestData.formLogin(loginModifications)); - } -}); - -/** - * Tests the collection of statistics related to login metadata. - */ -add_task(function test_logins_statistics() { - // Repeat the operation twice to test that histograms are not accumulated. - for (let repeating of [false, true]) { - triggerStatisticsCollection(); - - // Should record 1 in the bucket corresponding to the number of passwords. - testHistogram("PWMGR_NUM_SAVED_PASSWORDS", - { 10: 1 }); - - // Should record 1 in the bucket corresponding to the number of passwords. - testHistogram("PWMGR_NUM_HTTPAUTH_PASSWORDS", - { 1: 1 }); - - // For each saved login, should record 1 in the bucket corresponding to the - // age in days since the login was last used. - testHistogram("PWMGR_LOGIN_LAST_USED_DAYS", - { 0: 1, 1: 1, 7: 2, 29: 2, 356: 2, 750: 1 }); - - // Should record the number of logins without a username in bucket 0, and - // the number of logins with a username in bucket 1. - testHistogram("PWMGR_USERNAME_PRESENT", - { 0: 4, 1: 6 }); - } -}); - -/** - * Tests the collection of statistics related to hosts for which passowrd saving - * has been explicitly disabled. - */ -add_task(function test_disabledHosts_statistics() { - // Should record 1 in the bucket corresponding to the number of sites for - // which password saving is disabled. - Services.logins.setLoginSavingEnabled("http://www.example.com", false); - triggerStatisticsCollection(); - testHistogram("PWMGR_BLOCKLIST_NUM_SITES", { 1: 1 }); - - Services.logins.setLoginSavingEnabled("http://www.example.com", true); - triggerStatisticsCollection(); - testHistogram("PWMGR_BLOCKLIST_NUM_SITES", { 0: 1 }); -}); - -/** - * Tests the collection of statistics related to general settings. - */ -add_task(function test_settings_statistics() { - let oldRememberSignons = Services.prefs.getBoolPref("signon.rememberSignons"); - do_register_cleanup(function () { - Services.prefs.setBoolPref("signon.rememberSignons", oldRememberSignons); - }); - - // Repeat the operation twice per value to test that histograms are reset. - for (let remember of [false, true, false, true]) { - // This change should be observed immediately by the login service. - Services.prefs.setBoolPref("signon.rememberSignons", remember); - - triggerStatisticsCollection(); - - // Should record 1 in either bucket 0 or bucket 1 based on the preference. - testHistogram("PWMGR_SAVING_ENABLED", remember ? { 1: 1 } : { 0: 1 }); - } -}); diff --git a/toolkit/components/passwordmgr/test/unit/test_user_autocomplete_result.js b/toolkit/components/passwordmgr/test/unit/test_user_autocomplete_result.js deleted file mode 100644 index e1d250a76..000000000 --- a/toolkit/components/passwordmgr/test/unit/test_user_autocomplete_result.js +++ /dev/null @@ -1,488 +0,0 @@ -XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper", - "resource://gre/modules/LoginHelper.jsm"); -Cu.import("resource://gre/modules/LoginManagerContent.jsm"); -var nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", - Ci.nsILoginInfo, "init"); - -const PREF_INSECURE_FIELD_WARNING_ENABLED = "security.insecure_field_warning.contextual.enabled"; -const PREF_INSECURE_AUTOFILLFORMS_ENABLED = "signon.autofillForms.http"; - -let matchingLogins = []; -matchingLogins.push(new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null, - "", "emptypass1", "uname", "pword")); - -matchingLogins.push(new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null, - "tempuser1", "temppass1", "uname", "pword")); - -matchingLogins.push(new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null, - "testuser2", "testpass2", "uname", "pword")); - -matchingLogins.push(new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null, - "testuser3", "testpass3", "uname", "pword")); - -matchingLogins.push(new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null, - "zzzuser4", "zzzpass4", "uname", "pword")); - -let meta = matchingLogins[0].QueryInterface(Ci.nsILoginMetaInfo); -let dateAndTimeFormatter = new Intl.DateTimeFormat(undefined, - { day: "numeric", month: "short", year: "numeric" }); -let time = dateAndTimeFormatter.format(new Date(meta.timePasswordChanged)); -const LABEL_NO_USERNAME = "No username (" + time + ")"; - -let expectedResults = [ - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: true, - isSecure: true, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: true, - isSecure: false, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: "This connection is not secure. Logins entered here could be compromised. Learn More", - style: "insecureWarning" - }, { - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: true, - isSecure: true, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: true, - isSecure: false, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: "This connection is not secure. Logins entered here could be compromised. Learn More", - style: "insecureWarning" - }, { - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: true, - isSecure: true, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: true, - isSecure: false, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: true, - isSecure: true, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: true, - isSecure: false, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: false, - isSecure: true, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: false, - isSecure: false, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: "This connection is not secure. Logins entered here could be compromised. Learn More", - style: "insecureWarning" - }, { - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: false, - isSecure: true, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: true, - insecureAutoFillFormsEnabled: false, - isSecure: false, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: "This connection is not secure. Logins entered here could be compromised. Learn More", - style: "insecureWarning" - }, { - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: false, - isSecure: true, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [{ - value: "", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "tempuser1", - label: "tempuser1", - style: "login", - }, { - value: "testuser2", - label: "testuser2", - style: "login", - }, { - value: "testuser3", - label: "testuser3", - style: "login", - }, { - value: "zzzuser4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: false, - isSecure: false, - isPasswordField: false, - matchingLogins: matchingLogins, - items: [] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: false, - isSecure: true, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [{ - value: "emptypass1", - label: LABEL_NO_USERNAME, - style: "login", - }, { - value: "temppass1", - label: "tempuser1", - style: "login", - }, { - value: "testpass2", - label: "testuser2", - style: "login", - }, { - value: "testpass3", - label: "testuser3", - style: "login", - }, { - value: "zzzpass4", - label: "zzzuser4", - style: "login", - }] - }, - { - insecureFieldWarningEnabled: false, - insecureAutoFillFormsEnabled: false, - isSecure: false, - isPasswordField: true, - matchingLogins: matchingLogins, - items: [] - }, -]; - -add_task(function* test_all_patterns() { - LoginHelper.createLogger("UserAutoCompleteResult"); - expectedResults.forEach(pattern => { - Services.prefs.setBoolPref(PREF_INSECURE_FIELD_WARNING_ENABLED, - pattern.insecureFieldWarningEnabled); - Services.prefs.setBoolPref(PREF_INSECURE_AUTOFILLFORMS_ENABLED, - pattern.insecureAutoFillFormsEnabled); - let actual = new UserAutoCompleteResult("", pattern.matchingLogins, - { - isSecure: pattern.isSecure, - isPasswordField: pattern.isPasswordField - }); - pattern.items.forEach((item, index) => { - equal(actual.getValueAt(index), item.value); - equal(actual.getLabelAt(index), item.label); - equal(actual.getStyleAt(index), item.style); - }); - - if (pattern.items.length != 0) { - Assert.throws(() => actual.getValueAt(pattern.items.length), - /Index out of range\./); - - Assert.throws(() => actual.getLabelAt(pattern.items.length), - /Index out of range\./); - - Assert.throws(() => actual.removeValueAt(pattern.items.length, true), - /Index out of range\./); - } - }); -}); diff --git a/toolkit/components/passwordmgr/test/unit/xpcshell.ini b/toolkit/components/passwordmgr/test/unit/xpcshell.ini deleted file mode 100644 index 8f8c92a28..000000000 --- a/toolkit/components/passwordmgr/test/unit/xpcshell.ini +++ /dev/null @@ -1,46 +0,0 @@ -[DEFAULT] -head = head.js -tail = -support-files = data/** - -# Test JSON file access and import from SQLite, not applicable to Android. -[test_module_LoginImport.js] -skip-if = os == "android" -[test_module_LoginStore.js] -skip-if = os == "android" -[test_removeLegacySignonFiles.js] -skip-if = os == "android" - -# Test SQLite database backup and migration, applicable to Android only. -[test_storage_mozStorage.js] -skip-if = true || os != "android" # Bug 1171687: Needs fixing on Android - -# The following tests apply to any storage back-end. -[test_context_menu.js] -skip-if = os == "android" # The context menu isn't used on Android. -# LoginManagerContextMenu is only included for MOZ_BUILD_APP == 'browser'. -run-if = buildapp == "browser" -[test_dedupeLogins.js] -[test_disabled_hosts.js] -[test_getFormFields.js] -[test_getPasswordFields.js] -[test_getPasswordOrigin.js] -[test_isOriginMatching.js] -[test_legacy_empty_formSubmitURL.js] -[test_legacy_validation.js] -[test_logins_change.js] -[test_logins_decrypt_failure.js] -skip-if = os == "android" # Bug 1171687: Needs fixing on Android -[test_user_autocomplete_result.js] -skip-if = os == "android" -[test_logins_metainfo.js] -[test_logins_search.js] -[test_maybeImportLogin.js] -[test_notifications.js] -[test_OSCrypto_win.js] -skip-if = os != "win" -[test_recipes_add.js] -[test_recipes_content.js] -[test_search_schemeUpgrades.js] -[test_storage.js] -[test_telemetry.js] -- cgit v1.2.3