private static void performMigration(Context context) {
    final SharedPreferences appPrefs = forApp(context, disableMigrations);

    final int currentVersion = appPrefs.getInt(PREFS_VERSION_KEY, 0);
    Log.d(LOGTAG, "Current version = " + currentVersion + ", prefs version = " + PREFS_VERSION);

    if (currentVersion == PREFS_VERSION) {
      return;
    }

    Log.d(LOGTAG, "Performing migration");

    final Editor appEditor = appPrefs.edit();

    // The migration always moves prefs to the default profile, not
    // the current one. We might have to revisit this if we ever support
    // multiple profiles.
    final String defaultProfileName;
    try {
      defaultProfileName = GeckoProfile.getDefaultProfileName(context);
    } catch (Exception e) {
      throw new IllegalStateException("Failed to get default profile name for migration");
    }

    final Editor profileEditor =
        forProfileName(context, defaultProfileName, disableMigrations).edit();
    final Editor crashEditor = forCrashReporter(context, disableMigrations).edit();

    List<String> profileKeys;
    Editor pmEditor = null;

    for (int v = currentVersion + 1; v <= PREFS_VERSION; v++) {
      Log.d(LOGTAG, "Migrating to version = " + v);

      switch (v) {
        case 1:
          profileKeys = Arrays.asList(PROFILE_MIGRATIONS_0_TO_1);
          pmEditor = migrateFromPreferenceManager(context, appEditor, profileEditor, profileKeys);
          break;
        case 2:
          profileKeys = Arrays.asList(PROFILE_MIGRATIONS_1_TO_2);
          migrateCrashReporterSettings(appPrefs, appEditor, crashEditor, profileKeys);
          break;
      }
    }

    // Update prefs version accordingly.
    appEditor.putInt(PREFS_VERSION_KEY, PREFS_VERSION);

    appEditor.apply();
    profileEditor.apply();
    crashEditor.apply();
    if (pmEditor != null) {
      pmEditor.apply();
    }

    Log.d(LOGTAG, "All keys have been migrated");
  }