Bug 1582738 - ChromeProfileMigrator: Don't initialize crypto if there are no rows. r=Gijs
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Tue, 28 Jan 2020 10:50:10 +0000
changeset 512038 34fc136a1cc14fd2c53c293e95d8f7735f810015
parent 512037 b7c6f120153798e0d1d139ca3457234bb725061b
child 512039 8d7f2651eed8d29a9ba7bf65094e4bc2061419ff
push id37066
push usershindli@mozilla.com
push dateWed, 29 Jan 2020 03:50:12 +0000
treeherdermozilla-central@31e91b3d071e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1582738
milestone74.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1582738 - ChromeProfileMigrator: Don't initialize crypto if there are no rows. r=Gijs Initializing OSCrypto can lead to a useless macOS Keychain prompt when there are no logins to import. Differential Revision: https://phabricator.services.mozilla.com/D46616
browser/components/migration/ChromeProfileMigrator.jsm
browser/components/migration/tests/unit/AppData/LocalWithNoData/Google/Chrome/User Data/Default/Login Data
browser/components/migration/tests/unit/LibraryWithNoData/Application Support/Google/Chrome/Default/Login Data
browser/components/migration/tests/unit/LibraryWithNoData/Application Support/Google/Chrome/Local State
browser/components/migration/tests/unit/head_migration.js
browser/components/migration/tests/unit/test_Chrome_passwords.js
browser/components/migration/tests/unit/test_Chrome_passwords_emptySource.js
browser/components/migration/tests/unit/xpcshell.ini
--- a/browser/components/migration/ChromeProfileMigrator.jsm
+++ b/browser/components/migration/ChromeProfileMigrator.jsm
@@ -463,16 +463,23 @@ ChromeProfileMigrator.prototype._GetPass
         aCallback(false);
       });
       // If the promise was rejected we will have already called aCallback,
       // so we can just return here.
       if (!rows) {
         return;
       }
 
+      // If there are no relevant rows, return before initializing crypto and
+      // thus prompting for Keychain access on macOS.
+      if (!rows.length) {
+        aCallback(true);
+        return;
+      }
+
       let crypto;
       try {
         if (AppConstants.platform == "win") {
           let { OSCrypto } = ChromeUtils.import(
             "resource://gre/modules/OSCrypto.jsm"
           );
           crypto = new OSCrypto();
         } else if (AppConstants.platform == "macosx") {
copy from browser/components/migration/tests/unit/AppData/Local/Google/Chrome/User Data/Default/Login Data
copy to browser/components/migration/tests/unit/AppData/LocalWithNoData/Google/Chrome/User Data/Default/Login Data
index ac859eff6155306f5af57de81bab15fd424e6cdb..fd135624c430e4d83d0737406f515bce65d19e95
GIT binary patch
literal 24576
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
copy from browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Default/Login Data
copy to browser/components/migration/tests/unit/LibraryWithNoData/Application Support/Google/Chrome/Default/Login Data
index 6e03220c2c1239b34a3fd2197aaaaf80cd9c0dfa..b2d425eb4afbf299f07b14c844f58a0a64329658
GIT binary patch
literal 24576
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
copy from browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State
copy to browser/components/migration/tests/unit/LibraryWithNoData/Application Support/Google/Chrome/Local State
--- a/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State	
+++ b/browser/components/migration/tests/unit/LibraryWithNoData/Application Support/Google/Chrome/Local State	
@@ -5,17 +5,17 @@
         "active_time" : 1430950755.65137,
         "is_using_default_name" : true,
         "is_ephemeral" : false,
         "is_omitted_from_profile_list" : false,
         "user_name" : "",
         "background_apps" : false,
         "is_using_default_avatar" : true,
         "avatar_icon" : "chrome://theme/IDR_PROFILE_AVATAR_0",
-        "name" : "Person 1"
+        "name" : "Person With No Data"
       }
     },
     "profiles_created" : 1,
     "last_used" : "Default",
     "last_active_profiles" : [
       "Default"
     ]
   }
--- a/browser/components/migration/tests/unit/head_migration.js
+++ b/browser/components/migration/tests/unit/head_migration.js
@@ -46,32 +46,44 @@ var gProfD = do_get_profile();
 var { getAppInfo, newAppInfo, updateAppInfo } = ChromeUtils.import(
   "resource://testing-common/AppInfo.jsm"
 );
 updateAppInfo();
 
 /**
  * Migrates the requested resource and waits for the migration to be complete.
  */
-async function promiseMigration(migrator, resourceType, aProfile = null) {
+async function promiseMigration(
+  migrator,
+  resourceType,
+  aProfile = null,
+  succeeds = null
+) {
   // Ensure resource migration is available.
   let availableSources = await migrator.getMigrateData(aProfile, false);
   Assert.ok(
     (availableSources & resourceType) > 0,
     "Resource supported by migrator"
   );
+  let promises = [TestUtils.topicObserved("Migration:Ended")];
 
-  return new Promise(resolve => {
-    Services.obs.addObserver(function onMigrationEnded() {
-      Services.obs.removeObserver(onMigrationEnded, "Migration:Ended");
-      resolve();
-    }, "Migration:Ended");
+  if (succeeds !== null) {
+    // Check that the specific resource type succeeded
+    promises.push(
+      TestUtils.topicObserved(
+        succeeds ? "Migration:ItemAfterMigrate" : "Migration:ItemError",
+        (_, data) => data == resourceType
+      )
+    );
+  }
 
-    migrator.migrate(resourceType, null, aProfile);
-  });
+  // Start the migration.
+  migrator.migrate(resourceType, null, aProfile);
+
+  return Promise.all(promises);
 }
 
 /**
  * Replaces a directory service entry with a given nsIFile.
  */
 function registerFakePath(key, file) {
   let dirsvc = Services.dirsvc.QueryInterface(Ci.nsIProperties);
   let originalFile;
--- a/browser/components/migration/tests/unit/test_Chrome_passwords.js
+++ b/browser/components/migration/tests/unit/test_Chrome_passwords.js
@@ -276,17 +276,18 @@ add_task(async function test_importIntoE
 
   let logins = Services.logins.getAllLogins();
   Assert.equal(logins.length, 0, "There are no logins initially");
 
   // Migrate the logins.
   await promiseMigration(
     migrator,
     MigrationUtils.resourceTypes.PASSWORDS,
-    PROFILE
+    PROFILE,
+    true
   );
 
   logins = Services.logins.getAllLogins();
   Assert.equal(
     logins.length,
     TEST_LOGINS.length,
     "Check login count after importing the data"
   );
@@ -334,17 +335,18 @@ add_task(async function test_importExist
 
   for (let i = 0; i < newLogins.length; i++) {
     checkLoginsAreEqual(logins[i], newLogins[i], i + 1);
   }
   // Migrate the logins.
   await promiseMigration(
     migrator,
     MigrationUtils.resourceTypes.PASSWORDS,
-    PROFILE
+    PROFILE,
+    true
   );
 
   logins = Services.logins.getAllLogins();
   Assert.equal(
     logins.length,
     TEST_LOGINS.length,
     "Check there are still the same number of logins after re-importing the data"
   );
copy from browser/components/migration/tests/unit/test_Chrome_passwords.js
copy to browser/components/migration/tests/unit/test_Chrome_passwords_emptySource.js
--- a/browser/components/migration/tests/unit/test_Chrome_passwords.js
+++ b/browser/components/migration/tests/unit/test_Chrome_passwords_emptySource.js
@@ -1,360 +1,83 @@
 "use strict";
 
+/**
+ * Ensure that there is no dialog for OS crypto that blocks a migration when
+ * importing from an empty Login Data DB.
+ */
+
 const { AppConstants } = ChromeUtils.import(
   "resource://gre/modules/AppConstants.jsm"
 );
 
 const PROFILE = {
   id: "Default",
-  name: "Person 1",
+  name: "Person With No Data",
 };
 
-const TEST_LOGINS = [
-  {
-    id: 1, // id of the row in the chrome login db
-    username: "username",
-    password: "password",
-    origin: "https://c9.io",
-    formActionOrigin: "https://c9.io",
-    httpRealm: null,
-    usernameField: "inputEmail",
-    passwordField: "inputPassword",
-    timeCreated: 1437418416037,
-    timePasswordChanged: 1437418416037,
-    timesUsed: 1,
-  },
-  {
-    id: 2,
-    username: "username@gmail.com",
-    password: "password2",
-    origin: "https://accounts.google.com",
-    formActionOrigin: "https://accounts.google.com",
-    httpRealm: null,
-    usernameField: "Email",
-    passwordField: "Passwd",
-    timeCreated: 1437418446598,
-    timePasswordChanged: 1437418446598,
-    timesUsed: 6,
-  },
-  {
-    id: 3,
-    username: "username",
-    password: "password3",
-    origin: "https://www.facebook.com",
-    formActionOrigin: "https://www.facebook.com",
-    httpRealm: null,
-    usernameField: "email",
-    passwordField: "pass",
-    timeCreated: 1437418478851,
-    timePasswordChanged: 1437418478851,
-    timesUsed: 1,
-  },
-  {
-    id: 4,
-    username: "user",
-    password: "اقرأPÀßwörd",
-    origin: "http://httpbin.org",
-    formActionOrigin: null,
-    httpRealm: "me@kennethreitz.com", // Digest auth.
-    usernameField: "",
-    passwordField: "",
-    timeCreated: 1437787462368,
-    timePasswordChanged: 1437787462368,
-    timesUsed: 1,
-  },
-  {
-    id: 5,
-    username: "buser",
-    password: "bpassword",
-    origin: "http://httpbin.org",
-    formActionOrigin: null,
-    httpRealm: "Fake Realm", // Basic auth.
-    usernameField: "",
-    passwordField: "",
-    timeCreated: 1437787539233,
-    timePasswordChanged: 1437787539233,
-    timesUsed: 1,
-  },
-  {
-    id: 6,
-    username: "username",
-    password: "password6",
-    origin: "https://www.example.com",
-    formActionOrigin: "", // NULL `action_url`
-    httpRealm: null,
-    usernameField: "",
-    passwordField: "pass",
-    timeCreated: 1557291348878,
-    timePasswordChanged: 1557291348878,
-    timesUsed: 1,
-  },
-];
-
-var loginCrypto;
-var dbConn;
-
-async function promiseSetPassword(login) {
-  let encryptedString = await loginCrypto.encryptData(login.password);
-  info(`promiseSetPassword: ${encryptedString}`);
-  let passwordValue = new Uint8Array(
-    loginCrypto.stringToArray(encryptedString)
-  );
-  return dbConn.execute(
-    `UPDATE logins
-                         SET password_value = :password_value
-                         WHERE rowid = :rowid
-                        `,
-    { password_value: passwordValue, rowid: login.id }
-  );
-}
-
-function checkLoginsAreEqual(passwordManagerLogin, chromeLogin, id) {
-  passwordManagerLogin.QueryInterface(Ci.nsILoginMetaInfo);
-
-  Assert.equal(
-    passwordManagerLogin.username,
-    chromeLogin.username,
-    "The two logins ID " + id + " have the same username"
-  );
-  Assert.equal(
-    passwordManagerLogin.password,
-    chromeLogin.password,
-    "The two logins ID " + id + " have the same password"
-  );
-  Assert.equal(
-    passwordManagerLogin.origin,
-    chromeLogin.origin,
-    "The two logins ID " + id + " have the same origin"
-  );
-  Assert.equal(
-    passwordManagerLogin.formActionOrigin,
-    chromeLogin.formActionOrigin,
-    "The two logins ID " + id + " have the same formActionOrigin"
-  );
-  Assert.equal(
-    passwordManagerLogin.httpRealm,
-    chromeLogin.httpRealm,
-    "The two logins ID " + id + " have the same httpRealm"
-  );
-  Assert.equal(
-    passwordManagerLogin.usernameField,
-    chromeLogin.usernameField,
-    "The two logins ID " + id + " have the same usernameElement"
-  );
-  Assert.equal(
-    passwordManagerLogin.passwordField,
-    chromeLogin.passwordField,
-    "The two logins ID " + id + " have the same passwordElement"
-  );
-  Assert.equal(
-    passwordManagerLogin.timeCreated,
-    chromeLogin.timeCreated,
-    "The two logins ID " + id + " have the same timeCreated"
-  );
-  Assert.equal(
-    passwordManagerLogin.timePasswordChanged,
-    chromeLogin.timePasswordChanged,
-    "The two logins ID " + id + " have the same timePasswordChanged"
-  );
-  Assert.equal(
-    passwordManagerLogin.timesUsed,
-    chromeLogin.timesUsed,
-    "The two logins ID " + id + " have the same timesUsed"
-  );
-}
-
-function generateDifferentLogin(login) {
-  let newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(
-    Ci.nsILoginInfo
-  );
-
-  newLogin.init(
-    login.origin,
-    login.formActionOrigin,
-    null,
-    login.username,
-    login.password + 1,
-    login.usernameField + 1,
-    login.passwordField + 1
-  );
-  newLogin.QueryInterface(Ci.nsILoginMetaInfo);
-  newLogin.timeCreated = login.timeCreated + 1;
-  newLogin.timePasswordChanged = login.timePasswordChanged + 1;
-  newLogin.timesUsed = login.timesUsed + 1;
-  return newLogin;
-}
-
 add_task(async function setup() {
   let dirSvcPath;
   let pathId;
-  let profilePathSegments;
 
   // Use a mock service and account name to avoid a Keychain auth. prompt that
   // would block the test from finishing if Chrome has already created a matching
   // Keychain entry. This allows us to still exercise the keychain lookup code.
   // The mock encryption passphrase is used when the Keychain item isn't found.
   let mockMacOSKeychain = {
     passphrase: "bW96aWxsYWZpcmVmb3g=",
     serviceName: "TESTING Chrome Safe Storage",
     accountName: "TESTING Chrome",
   };
   if (AppConstants.platform == "macosx") {
-    let { ChromeMacOSLoginCrypto } = ChromeUtils.import(
-      "resource:///modules/ChromeMacOSLoginCrypto.jsm"
-    );
-    loginCrypto = new ChromeMacOSLoginCrypto(
-      mockMacOSKeychain.serviceName,
-      mockMacOSKeychain.accountName,
-      mockMacOSKeychain.passphrase
-    );
-    dirSvcPath = "Library/";
+    dirSvcPath = "LibraryWithNoData/";
     pathId = "ULibDir";
-    profilePathSegments = [
-      "Application Support",
-      "Google",
-      "Chrome",
-      "Default",
-      "Login Data",
-    ];
   } else if (AppConstants.platform == "win") {
-    const { OSCrypto } = ChromeUtils.import(
-      "resource://gre/modules/OSCrypto.jsm"
-    );
-    loginCrypto = new OSCrypto();
-    dirSvcPath = "AppData/Local/";
+    dirSvcPath = "AppData/LocalWithNoData/";
     pathId = "LocalAppData";
-    profilePathSegments = [
-      "Google",
-      "Chrome",
-      "User Data",
-      "Default",
-      "Login Data",
-    ];
   } else {
     throw new Error("Not implemented");
   }
   let dirSvcFile = do_get_file(dirSvcPath);
   registerFakePath(pathId, dirSvcFile);
 
-  // We don't import osfile.jsm until after registering the fake path, because
-  // importing osfile will sometimes greedily fetch certain path identifiers
-  // from the dir service, which means they get cached, which means we can't
-  // register a fake path for them anymore.
-  const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
-  info(OS.Path.join(dirSvcFile.path, ...profilePathSegments));
-  let loginDataFilePath = OS.Path.join(dirSvcFile.path, ...profilePathSegments);
-  dbConn = await Sqlite.openConnection({ path: loginDataFilePath });
-
   if (AppConstants.platform == "macosx") {
     let migrator = await MigrationUtils.getMigrator("chrome");
     Object.assign(migrator.wrappedJSObject, {
       _keychainServiceName: mockMacOSKeychain.serviceName,
       _keychainAccountName: mockMacOSKeychain.accountName,
-      _keychainMockPassphrase: mockMacOSKeychain.passphrase,
+      // No `_keychainMockPassphrase` as we don't want to mock the OS dialog as
+      // it shouldn't appear.
     });
   }
 
   registerCleanupFunction(() => {
     Services.logins.removeAllLogins();
-    if (loginCrypto.finalize) {
-      loginCrypto.finalize();
-    }
-    return dbConn.close();
   });
 });
 
-add_task(async function test_importIntoEmptyDB() {
-  for (let login of TEST_LOGINS) {
-    await promiseSetPassword(login);
-  }
-
+add_task(async function test_importEmptyDBWithoutAuthPrompts() {
   let migrator = await MigrationUtils.getMigrator("chrome");
   Assert.ok(
     await migrator.isSourceAvailable(),
     "Sanity check the source exists"
   );
 
   let logins = Services.logins.getAllLogins();
   Assert.equal(logins.length, 0, "There are no logins initially");
 
-  // Migrate the logins.
+  // Migrate the logins. If an OS dialog (e.g. Keychain) blocks this the test
+  // would timeout.
   await promiseMigration(
     migrator,
     MigrationUtils.resourceTypes.PASSWORDS,
-    PROFILE
+    PROFILE,
+    true
   );
 
   logins = Services.logins.getAllLogins();
-  Assert.equal(
-    logins.length,
-    TEST_LOGINS.length,
-    "Check login count after importing the data"
-  );
+  Assert.equal(logins.length, 0, "Check login count after importing the data");
   Assert.equal(
     logins.length,
     MigrationUtils._importQuantities.logins,
     "Check telemetry matches the actual import."
   );
-
-  for (let i = 0; i < TEST_LOGINS.length; i++) {
-    checkLoginsAreEqual(logins[i], TEST_LOGINS[i], i + 1);
-  }
 });
-
-// Test that existing logins for the same primary key don't get overwritten
-add_task(async function test_importExistingLogins() {
-  let migrator = await MigrationUtils.getMigrator("chrome");
-  Assert.ok(
-    await migrator.isSourceAvailable(),
-    "Sanity check the source exists"
-  );
-
-  Services.logins.removeAllLogins();
-  let logins = Services.logins.getAllLogins();
-  Assert.equal(
-    logins.length,
-    0,
-    "There are no logins after removing all of them"
-  );
-
-  let newLogins = [];
-
-  // Create 3 new logins that are different but where the key properties are still the same.
-  for (let i = 0; i < 3; i++) {
-    newLogins.push(generateDifferentLogin(TEST_LOGINS[i]));
-    Services.logins.addLogin(newLogins[i]);
-  }
-
-  logins = Services.logins.getAllLogins();
-  Assert.equal(
-    logins.length,
-    newLogins.length,
-    "Check login count after the insertion"
-  );
-
-  for (let i = 0; i < newLogins.length; i++) {
-    checkLoginsAreEqual(logins[i], newLogins[i], i + 1);
-  }
-  // Migrate the logins.
-  await promiseMigration(
-    migrator,
-    MigrationUtils.resourceTypes.PASSWORDS,
-    PROFILE
-  );
-
-  logins = Services.logins.getAllLogins();
-  Assert.equal(
-    logins.length,
-    TEST_LOGINS.length,
-    "Check there are still the same number of logins after re-importing the data"
-  );
-  Assert.equal(
-    logins.length,
-    MigrationUtils._importQuantities.logins,
-    "Check telemetry matches the actual import."
-  );
-
-  for (let i = 0; i < newLogins.length; i++) {
-    checkLoginsAreEqual(logins[i], newLogins[i], i + 1);
-  }
-});
--- a/browser/components/migration/tests/unit/xpcshell.ini
+++ b/browser/components/migration/tests/unit/xpcshell.ini
@@ -10,16 +10,20 @@ support-files =
 skip-if = os != "win"
 [test_Chrome_bookmarks.js]
 [test_Chrome_cookies.js]
 skip-if = os != "mac" # Relies on ULibDir
 [test_Chrome_history.js]
 skip-if = os != "mac" # Relies on ULibDir
 [test_Chrome_passwords.js]
 skip-if = os != "win" && os != "mac"
+[test_Chrome_passwords_emptySource.js]
+skip-if = os != "win" && os != "mac"
+support-files =
+  LibraryWithNoData/**
 [test_ChromeMigrationUtils.js]
 [test_ChromeMigrationUtils_path.js]
 [test_Edge_db_migration.js]
 skip-if = os != "win"
 [test_fx_telemetry.js]
 [test_IE_bookmarks.js]
 skip-if = !(os == "win" && bits == 64) # bug 1392396
 [test_IE_cookies.js]