summaryrefslogtreecommitdiffstats
path: root/browser/components/migration/tests/unit/test_Chrome_credit_cards.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/migration/tests/unit/test_Chrome_credit_cards.js')
-rw-r--r--browser/components/migration/tests/unit/test_Chrome_credit_cards.js239
1 files changed, 239 insertions, 0 deletions
diff --git a/browser/components/migration/tests/unit/test_Chrome_credit_cards.js b/browser/components/migration/tests/unit/test_Chrome_credit_cards.js
new file mode 100644
index 0000000000..5c4d3517d2
--- /dev/null
+++ b/browser/components/migration/tests/unit/test_Chrome_credit_cards.js
@@ -0,0 +1,239 @@
+/* Any copyright is dedicated to the Public Domain.
+http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* global structuredClone */
+
+const PROFILE = {
+ id: "Default",
+ name: "Default",
+};
+
+const PAYMENT_METHODS = [
+ {
+ name_on_card: "Name Name",
+ card_number: "4532962432748929", // Visa
+ expiration_month: 3,
+ expiration_year: 2027,
+ },
+ {
+ name_on_card: "Name Name Name",
+ card_number: "5359908373796416", // Mastercard
+ expiration_month: 5,
+ expiration_year: 2028,
+ },
+ {
+ name_on_card: "Name",
+ card_number: "346624461807588", // AMEX
+ expiration_month: 4,
+ expiration_year: 2026,
+ },
+];
+
+let OSKeyStoreTestUtils;
+add_setup(async function os_key_store_setup() {
+ ({ OSKeyStoreTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/OSKeyStoreTestUtils.sys.mjs"
+ ));
+ OSKeyStoreTestUtils.setup();
+ registerCleanupFunction(async function cleanup() {
+ await OSKeyStoreTestUtils.cleanup();
+ });
+});
+
+let rootDir = do_get_file("chromefiles/", true);
+
+function checkCardsAreEqual(importedCard, testCard, id) {
+ const CC_NUMBER_RE = /^(\*+)(.{4})$/;
+
+ Assert.equal(
+ importedCard["cc-name"],
+ testCard.name_on_card,
+ "The two logins ID " + id + " have the same name on card"
+ );
+
+ let matches = CC_NUMBER_RE.exec(importedCard["cc-number"]);
+ Assert.notEqual(matches, null);
+ Assert.equal(importedCard["cc-number"].length, testCard.card_number.length);
+ Assert.equal(testCard.card_number.endsWith(matches[2]), true);
+ Assert.notEqual(importedCard["cc-number-encrypted"], "");
+
+ Assert.equal(
+ importedCard["cc-exp-month"],
+ testCard.expiration_month,
+ "The two logins ID " + id + " have the same expiration month"
+ );
+ Assert.equal(
+ importedCard["cc-exp-year"],
+ testCard.expiration_year,
+ "The two logins ID " + id + " have the same expiration year"
+ );
+}
+
+add_task(async function setup_fakePaths() {
+ let pathId;
+ if (AppConstants.platform == "macosx") {
+ pathId = "ULibDir";
+ } else if (AppConstants.platform == "win") {
+ pathId = "LocalAppData";
+ } else {
+ pathId = "Home";
+ }
+ registerFakePath(pathId, rootDir);
+});
+
+add_task(async function test_credit_cards() {
+ if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
+ todo_check_true(
+ OSKeyStoreTestUtils.canTestOSKeyStoreLogin(),
+ "Cannot test OS key store login on official builds."
+ );
+ return;
+ }
+
+ let loginCrypto;
+ let profilePathSegments;
+
+ let mockMacOSKeychain = {
+ passphrase: "bW96aWxsYWZpcmVmb3g=",
+ serviceName: "TESTING Chrome Safe Storage",
+ accountName: "TESTING Chrome",
+ };
+ if (AppConstants.platform == "macosx") {
+ let { ChromeMacOSLoginCrypto } = ChromeUtils.importESModule(
+ "resource:///modules/ChromeMacOSLoginCrypto.sys.mjs"
+ );
+ loginCrypto = new ChromeMacOSLoginCrypto(
+ mockMacOSKeychain.serviceName,
+ mockMacOSKeychain.accountName,
+ mockMacOSKeychain.passphrase
+ );
+ profilePathSegments = [
+ "Application Support",
+ "Google",
+ "Chrome",
+ "Default",
+ ];
+ } else if (AppConstants.platform == "win") {
+ let { ChromeWindowsLoginCrypto } = ChromeUtils.importESModule(
+ "resource:///modules/ChromeWindowsLoginCrypto.sys.mjs"
+ );
+ loginCrypto = new ChromeWindowsLoginCrypto("Chrome");
+ profilePathSegments = ["Google", "Chrome", "User Data", "Default"];
+ } else {
+ throw new Error("Not implemented");
+ }
+
+ let target = rootDir.clone();
+ let defaultFolderPath = PathUtils.join(target.path, ...profilePathSegments);
+ let webDataPath = PathUtils.join(defaultFolderPath, "Web Data");
+ let localStatePath = defaultFolderPath.replace("Default", "");
+
+ await IOUtils.makeDirectory(defaultFolderPath, {
+ createAncestor: true,
+ ignoreExisting: true,
+ });
+
+ // Copy Web Data database into Default profile
+ const sourcePathWebData = do_get_file(
+ "AppData/Local/Google/Chrome/User Data/Default/Web Data"
+ ).path;
+ await IOUtils.copy(sourcePathWebData, webDataPath);
+
+ const sourcePathLocalState = do_get_file(
+ "AppData/Local/Google/Chrome/User Data/Local State"
+ ).path;
+ await IOUtils.copy(sourcePathLocalState, localStatePath);
+
+ let dbConn = await Sqlite.openConnection({ path: webDataPath });
+
+ for (let card of PAYMENT_METHODS) {
+ let encryptedCardNumber = await loginCrypto.encryptData(card.card_number);
+ let cardNumberEncryptedValue = new Uint8Array(
+ loginCrypto.stringToArray(encryptedCardNumber)
+ );
+
+ let cardCopy = structuredClone(card);
+
+ cardCopy.card_number_encrypted = cardNumberEncryptedValue;
+ delete cardCopy.card_number;
+
+ await dbConn.execute(
+ `INSERT INTO credit_cards
+ (name_on_card, card_number_encrypted, expiration_month, expiration_year)
+ VALUES (:name_on_card, :card_number_encrypted, :expiration_month, :expiration_year)
+ `,
+ cardCopy
+ );
+ }
+
+ await dbConn.close();
+
+ let migrator = await MigrationUtils.getMigrator("chrome");
+ if (AppConstants.platform == "macosx") {
+ Object.assign(migrator, {
+ _keychainServiceName: mockMacOSKeychain.serviceName,
+ _keychainAccountName: mockMacOSKeychain.accountName,
+ _keychainMockPassphrase: mockMacOSKeychain.passphrase,
+ });
+ }
+ Assert.ok(
+ await migrator.isSourceAvailable(),
+ "Sanity check the source exists"
+ );
+
+ Services.prefs.setBoolPref(
+ "browser.migrate.chrome.payment_methods.enabled",
+ false
+ );
+ Assert.ok(
+ !(
+ (await migrator.getMigrateData(PROFILE)) &
+ MigrationUtils.resourceTypes.PAYMENT_METHODS
+ ),
+ "Should be able to disable migrating payment methods"
+ );
+ // Clear the cached resources now so that a re-check for payment methods
+ // will look again.
+ delete migrator._resourcesByProfile[PROFILE.id];
+
+ Services.prefs.setBoolPref(
+ "browser.migrate.chrome.payment_methods.enabled",
+ true
+ );
+
+ Assert.ok(
+ (await migrator.getMigrateData(PROFILE)) &
+ MigrationUtils.resourceTypes.PAYMENT_METHODS,
+ "Should be able to enable migrating payment methods"
+ );
+
+ let { formAutofillStorage } = ChromeUtils.importESModule(
+ "resource://autofill/FormAutofillStorage.sys.mjs"
+ );
+ await formAutofillStorage.initialize();
+
+ await promiseMigration(
+ migrator,
+ MigrationUtils.resourceTypes.PAYMENT_METHODS,
+ PROFILE
+ );
+
+ let cards = await formAutofillStorage.creditCards.getAll();
+
+ Assert.equal(
+ cards.length,
+ PAYMENT_METHODS.length,
+ "Check there are still the same number of credit cards after re-importing the data"
+ );
+ Assert.equal(
+ cards.length,
+ MigrationUtils._importQuantities.cards,
+ "Check telemetry matches the actual import."
+ );
+
+ for (let i = 0; i < PAYMENT_METHODS.length; i++) {
+ checkCardsAreEqual(cards[i], PAYMENT_METHODS[i], i + 1);
+ }
+});