// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/password_manager/core/browser/login_database.h"

#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/bind.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/pickle.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/common/password_form.h"
#include "components/os_crypt/os_crypt.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/psl_matching_helper.h"
#include "components/password_manager/core/browser/sql_table_builder.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/sync/protocol/entity_metadata.pb.h"
#include "components/sync/protocol/model_type_state.pb.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/origin.h"
#include "url/url_constants.h"

using autofill::PasswordForm;

namespace password_manager {

// The current version number of the login database schema.
const int kCurrentVersionNumber = 21;
// The oldest version of the schema such that a legacy Chrome client using that
// version can still read/write the current database.
const int kCompatibleVersionNumber = 19;

base::Pickle SerializeValueElementPairs(
    const autofill::ValueElementVector& vec) {
  base::Pickle p;
  for (size_t i = 0; i < vec.size(); ++i) {
    p.WriteString16(vec[i].first);
    p.WriteString16(vec[i].second);
  }
  return p;
}

autofill::ValueElementVector DeserializeValueElementPairs(
    const base::Pickle& p) {
  autofill::ValueElementVector ret;
  base::string16 value;
  base::string16 field_name;

  base::PickleIterator iterator(p);
  while (iterator.ReadString16(&value)) {
    bool name_success = iterator.ReadString16(&field_name);
    DCHECK(name_success);
    ret.push_back(autofill::ValueElementPair(value, field_name));
  }
  return ret;
}

namespace {

// A simple class for scoping a login database transaction. This does not
// support rollback since the login database doesn't either.
class ScopedTransaction {
 public:
  explicit ScopedTransaction(LoginDatabase* db) : db_(db) {
    db_->BeginTransaction();
  }
  ~ScopedTransaction() { db_->CommitTransaction(); }

 private:
  LoginDatabase* db_;
  DISALLOW_COPY_AND_ASSIGN(ScopedTransaction);
};

// Convenience enum for interacting with SQL queries that use all the columns.
enum LoginDatabaseTableColumns {
  COLUMN_ORIGIN_URL = 0,
  COLUMN_ACTION_URL,
  COLUMN_USERNAME_ELEMENT,
  COLUMN_USERNAME_VALUE,
  COLUMN_PASSWORD_ELEMENT,
  COLUMN_PASSWORD_VALUE,
  COLUMN_SUBMIT_ELEMENT,
  COLUMN_SIGNON_REALM,
  COLUMN_PREFERRED,
  COLUMN_DATE_CREATED,
  COLUMN_BLACKLISTED_BY_USER,
  COLUMN_SCHEME,
  COLUMN_PASSWORD_TYPE,
  COLUMN_TIMES_USED,
  COLUMN_FORM_DATA,
  COLUMN_DATE_SYNCED,
  COLUMN_DISPLAY_NAME,
  COLUMN_ICON_URL,
  COLUMN_FEDERATION_URL,
  COLUMN_SKIP_ZERO_CLICK,
  COLUMN_GENERATION_UPLOAD_STATUS,
  COLUMN_POSSIBLE_USERNAME_PAIRS,
  COLUMN_ID,
  COLUMN_NUM  // Keep this last.
};

enum class HistogramSize { SMALL, LARGE };

// An enum for UMA reporting. Add values to the end only.
enum DatabaseInitError {
  INIT_OK,
  OPEN_FILE_ERROR,
  START_TRANSACTION_ERROR,
  META_TABLE_INIT_ERROR,
  INCOMPATIBLE_VERSION,
  INIT_LOGINS_ERROR,
  INIT_STATS_ERROR,
  MIGRATION_ERROR,
  COMMIT_TRANSACTION_ERROR,

  DATABASE_INIT_ERROR_COUNT,
};

// Struct to hold table builder for "logins", "sync_entities_metadata", and
// "sync_model_metadata" tables.
struct SQLTableBuilders {
  SQLTableBuilder* logins;
  SQLTableBuilder* sync_entities_metadata;
  SQLTableBuilder* sync_model_metadata;
};

void BindAddStatement(const PasswordForm& form,
                      const std::string& encrypted_password,
                      sql::Statement* s) {
  s->BindString(COLUMN_ORIGIN_URL, form.origin.spec());
  s->BindString(COLUMN_ACTION_URL, form.action.spec());
  s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element);
  s->BindString16(COLUMN_USERNAME_VALUE, form.username_value);
  s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element);
  s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(),
              static_cast<int>(encrypted_password.length()));
  s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element);
  s->BindString(COLUMN_SIGNON_REALM, form.signon_realm);
  s->BindInt(COLUMN_PREFERRED, form.preferred);
  s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToInternalValue());
  s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user);
  s->BindInt(COLUMN_SCHEME, form.scheme);
  s->BindInt(COLUMN_PASSWORD_TYPE, form.type);
  s->BindInt(COLUMN_TIMES_USED, form.times_used);
  base::Pickle form_data_pickle;
  autofill::SerializeFormData(form.form_data, &form_data_pickle);
  s->BindBlob(COLUMN_FORM_DATA,
              form_data_pickle.data(),
              form_data_pickle.size());
  s->BindInt64(COLUMN_DATE_SYNCED, form.date_synced.ToInternalValue());
  s->BindString16(COLUMN_DISPLAY_NAME, form.display_name);
  s->BindString(COLUMN_ICON_URL, form.icon_url.spec());
  // An empty Origin serializes as "null" which would be strange to store here.
  s->BindString(COLUMN_FEDERATION_URL,
                form.federation_origin.opaque()
                    ? std::string()
                    : form.federation_origin.Serialize());
  s->BindInt(COLUMN_SKIP_ZERO_CLICK, form.skip_zero_click);
  s->BindInt(COLUMN_GENERATION_UPLOAD_STATUS, form.generation_upload_status);
  base::Pickle usernames_pickle =
      SerializeValueElementPairs(form.other_possible_usernames);
  s->BindBlob(COLUMN_POSSIBLE_USERNAME_PAIRS, usernames_pickle.data(),
              usernames_pickle.size());
}

void AddCallback(int err, sql::Statement* /*stmt*/) {
  if (err == 19 /*SQLITE_CONSTRAINT*/)
    DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form";
}

bool DoesMatchConstraints(const PasswordForm& form) {
  if (!IsValidAndroidFacetURI(form.signon_realm) && form.origin.is_empty()) {
    DLOG(ERROR) << "Constraint violation: form.origin is empty";
    return false;
  }
  if (form.signon_realm.empty()) {
    DLOG(ERROR) << "Constraint violation: form.signon_realm is empty";
    return false;
  }
  return true;
}

void LogDatabaseInitError(DatabaseInitError error) {
  UMA_HISTOGRAM_ENUMERATION("PasswordManager.LoginDatabaseInit", error,
                            DATABASE_INIT_ERROR_COUNT);
}

// UMA_* macros assume that the name never changes. This is a helper function
// where this assumption doesn't hold.
void LogDynamicUMAStat(const std::string& name,
                       int sample,
                       int min,
                       int max,
                       int bucket_count) {
  base::HistogramBase* counter = base::Histogram::FactoryGet(
      name, min, max, bucket_count,
      base::HistogramBase::kUmaTargetedHistogramFlag);
  counter->Add(sample);
}

void LogAccountStat(const std::string& name, int sample) {
  LogDynamicUMAStat(name, sample, 0, 32, 6);
}

void LogTimesUsedStat(const std::string& name, int sample) {
  LogDynamicUMAStat(name, sample, 0, 100, 10);
}

void LogNumberOfAccountsForScheme(const std::string& scheme, int sample) {
  LogDynamicUMAStat("PasswordManager.TotalAccountsHiRes.WithScheme." + scheme,
                    sample, 1, 1000, 100);
}

void LogNumberOfAccountsReusingPassword(const std::string& suffix,
                                        int sample,
                                        HistogramSize histogram_size) {
  int max = histogram_size == HistogramSize::LARGE ? 500 : 100;
  int bucket_count = histogram_size == HistogramSize::LARGE ? 50 : 20;
  LogDynamicUMAStat("PasswordManager.AccountsReusingPassword." + suffix, sample,
                    1, max, bucket_count);
}

// Records password reuse metrics given the |signon_realms| corresponding to a
// set of accounts that reuse the same password. See histograms.xml for details.
void LogPasswordReuseMetrics(const std::vector<std::string>& signon_realms) {
  struct StatisticsPerScheme {
    StatisticsPerScheme() : num_total_accounts(0) {}

    // The number of accounts for each registry controlled domain.
    std::map<std::string, int> num_accounts_per_registry_controlled_domain;

    // The number of accounts for each domain.
    std::map<std::string, int> num_accounts_per_domain;

    // Total number of accounts with this scheme. This equals the sum of counts
    // in either of the above maps.
    int num_total_accounts;
  };

  // The scheme (i.e. protocol) of the origin, not PasswordForm::scheme.
  enum Scheme { SCHEME_HTTP, SCHEME_HTTPS };
  const Scheme kAllSchemes[] = {SCHEME_HTTP, SCHEME_HTTPS};

  StatisticsPerScheme statistics[base::size(kAllSchemes)];
  std::map<std::string, std::string> domain_to_registry_controlled_domain;

  for (const std::string& signon_realm : signon_realms) {
    const GURL signon_realm_url(signon_realm);
    const std::string domain = signon_realm_url.host();
    if (domain.empty())
      continue;

    if (!domain_to_registry_controlled_domain.count(domain)) {
      domain_to_registry_controlled_domain[domain] =
          GetRegistryControlledDomain(signon_realm_url);
      if (domain_to_registry_controlled_domain[domain].empty())
        domain_to_registry_controlled_domain[domain] = domain;
    }
    const std::string& registry_controlled_domain =
        domain_to_registry_controlled_domain[domain];

    Scheme scheme = SCHEME_HTTP;
    static_assert(base::size(kAllSchemes) == 2, "Update this logic");
    if (signon_realm_url.SchemeIs(url::kHttpsScheme))
      scheme = SCHEME_HTTPS;
    else if (!signon_realm_url.SchemeIs(url::kHttpScheme))
      continue;

    statistics[scheme].num_accounts_per_domain[domain]++;
    statistics[scheme].num_accounts_per_registry_controlled_domain
        [registry_controlled_domain]++;
    statistics[scheme].num_total_accounts++;
  }

  // For each "source" account of either scheme, count the number of "target"
  // accounts reusing the same password (of either scheme).
  for (const Scheme scheme : kAllSchemes) {
    for (const auto& kv : statistics[scheme].num_accounts_per_domain) {
      const std::string& domain(kv.first);
      const int num_accounts_per_domain(kv.second);
      const std::string& registry_controlled_domain =
          domain_to_registry_controlled_domain[domain];

      Scheme other_scheme = scheme == SCHEME_HTTP ? SCHEME_HTTPS : SCHEME_HTTP;
      static_assert(base::size(kAllSchemes) == 2, "Update |other_scheme|");

      // Discount the account at hand from the number of accounts with the same
      // domain and scheme.
      int num_accounts_for_same_domain[base::size(kAllSchemes)] = {};
      num_accounts_for_same_domain[scheme] =
          statistics[scheme].num_accounts_per_domain[domain] - 1;
      num_accounts_for_same_domain[other_scheme] =
          statistics[other_scheme].num_accounts_per_domain[domain];

      // By definition, a PSL match requires the scheme to be the same.
      int num_psl_matching_accounts =
          statistics[scheme].num_accounts_per_registry_controlled_domain
              [registry_controlled_domain] -
          statistics[scheme].num_accounts_per_domain[domain];

      // Discount PSL matches from the number of accounts with different domains
      // but the same scheme.
      int num_accounts_for_different_domain[base::size(kAllSchemes)] = {};
      num_accounts_for_different_domain[scheme] =
          statistics[scheme].num_total_accounts -
          statistics[scheme].num_accounts_per_registry_controlled_domain
              [registry_controlled_domain];
      num_accounts_for_different_domain[other_scheme] =
          statistics[other_scheme].num_total_accounts -
          statistics[other_scheme].num_accounts_per_domain[domain];

      std::string source_realm_kind =
          scheme == SCHEME_HTTP ? "FromHttpRealm" : "FromHttpsRealm";
      static_assert(base::size(kAllSchemes) == 2, "Update |source_realm_kind|");

      // So far, the calculation has been carried out once per "source" domain,
      // but the metrics need to be recorded on a per-account basis. The set of
      // metrics are the same for all accounts for the same domain, so simply
      // report them as many times as accounts.
      for (int i = 0; i < num_accounts_per_domain; ++i) {
        LogNumberOfAccountsReusingPassword(
            source_realm_kind + ".OnHttpRealmWithSameHost",
            num_accounts_for_same_domain[SCHEME_HTTP], HistogramSize::SMALL);
        LogNumberOfAccountsReusingPassword(
            source_realm_kind + ".OnHttpsRealmWithSameHost",
            num_accounts_for_same_domain[SCHEME_HTTPS], HistogramSize::SMALL);
        LogNumberOfAccountsReusingPassword(
            source_realm_kind + ".OnPSLMatchingRealm",
            num_psl_matching_accounts, HistogramSize::SMALL);

        LogNumberOfAccountsReusingPassword(
            source_realm_kind + ".OnHttpRealmWithDifferentHost",
            num_accounts_for_different_domain[SCHEME_HTTP],
            HistogramSize::LARGE);
        LogNumberOfAccountsReusingPassword(
            source_realm_kind + ".OnHttpsRealmWithDifferentHost",
            num_accounts_for_different_domain[SCHEME_HTTPS],
            HistogramSize::LARGE);

        LogNumberOfAccountsReusingPassword(
            source_realm_kind + ".OnAnyRealmWithDifferentHost",
            num_accounts_for_different_domain[SCHEME_HTTP] +
                num_accounts_for_different_domain[SCHEME_HTTPS],
            HistogramSize::LARGE);
      }
    }
  }
}

// Seals the version of the given builders. This is method should be always used
// to seal versions of all builder to make sure all builders are at the same
// version.
void SealVersion(SQLTableBuilders builders, unsigned expected_version) {
  unsigned logins_version = builders.logins->SealVersion();
  DCHECK_EQ(expected_version, logins_version);

  unsigned sync_entities_metadata_version =
      builders.sync_entities_metadata->SealVersion();
  DCHECK_EQ(expected_version, sync_entities_metadata_version);

  unsigned sync_model_metadata_version =
      builders.sync_model_metadata->SealVersion();
  DCHECK_EQ(expected_version, sync_model_metadata_version);
}

// Teaches |builders| about the different DB schemes in different versions.
void InitializeBuilders(SQLTableBuilders builders) {
  // Versions 0 and 1, which are the same.
  builders.logins->AddColumnToUniqueKey("origin_url", "VARCHAR NOT NULL");
  builders.logins->AddColumn("action_url", "VARCHAR");
  builders.logins->AddColumnToUniqueKey("username_element", "VARCHAR");
  builders.logins->AddColumnToUniqueKey("username_value", "VARCHAR");
  builders.logins->AddColumnToUniqueKey("password_element", "VARCHAR");
  builders.logins->AddColumn("password_value", "BLOB");
  builders.logins->AddColumn("submit_element", "VARCHAR");
  builders.logins->AddColumnToUniqueKey("signon_realm", "VARCHAR NOT NULL");
  builders.logins->AddColumn("ssl_valid", "INTEGER NOT NULL");
  builders.logins->AddColumn("preferred", "INTEGER NOT NULL");
  builders.logins->AddColumn("date_created", "INTEGER NOT NULL");
  builders.logins->AddColumn("blacklisted_by_user", "INTEGER NOT NULL");
  builders.logins->AddColumn("scheme", "INTEGER NOT NULL");
  builders.logins->AddIndex("logins_signon", {"signon_realm"});
  SealVersion(builders, /*expected_version=*/0u);
  SealVersion(builders, /*expected_version=*/1u);

  // Version 2.
  builders.logins->AddColumn("password_type", "INTEGER");
  builders.logins->AddColumn("possible_usernames", "BLOB");
  SealVersion(builders, /*expected_version=*/2u);

  // Version 3.
  builders.logins->AddColumn("times_used", "INTEGER");
  SealVersion(builders, /*expected_version=*/3u);

  // Version 4.
  builders.logins->AddColumn("form_data", "BLOB");
  SealVersion(builders, /*expected_version=*/4u);

  // Version 5.
  builders.logins->AddColumn("use_additional_auth", "INTEGER");
  SealVersion(builders, /*expected_version=*/5u);

  // Version 6.
  builders.logins->AddColumn("date_synced", "INTEGER");
  SealVersion(builders, /*expected_version=*/6u);

  // Version 7.
  builders.logins->AddColumn("display_name", "VARCHAR");
  builders.logins->AddColumn("avatar_url", "VARCHAR");
  builders.logins->AddColumn("federation_url", "VARCHAR");
  builders.logins->AddColumn("is_zero_click", "INTEGER");
  SealVersion(builders, /*expected_version=*/7u);

  // Version 8.
  SealVersion(builders, /*expected_version=*/8u);
  // Version 9.
  SealVersion(builders, /*expected_version=*/9u);
  // Version 10.
  builders.logins->DropColumn("use_additional_auth");
  SealVersion(builders, /*expected_version=*/10u);

  // Version 11.
  builders.logins->RenameColumn("is_zero_click", "skip_zero_click");
  SealVersion(builders, /*expected_version=*/11u);

  // Version 12.
  builders.logins->AddColumn("generation_upload_status", "INTEGER");
  SealVersion(builders, /*expected_version=*/12u);

  // Version 13.
  SealVersion(builders, /*expected_version=*/13u);
  // Version 14.
  builders.logins->RenameColumn("avatar_url", "icon_url");
  SealVersion(builders, /*expected_version=*/14u);

  // Version 15.
  SealVersion(builders, /*expected_version=*/15u);
  // Version 16.
  SealVersion(builders, /*expected_version=*/16u);
  // Version 17.
  SealVersion(builders, /*expected_version=*/17u);

  // Version 18.
  builders.logins->DropColumn("ssl_valid");
  SealVersion(builders, /*expected_version=*/18u);

  // Version 19.
  builders.logins->DropColumn("possible_usernames");
  builders.logins->AddColumn("possible_username_pairs", "BLOB");
  SealVersion(builders, /*expected_version=*/19u);

  // Version 20.
  builders.logins->AddColumnToPrimaryKey("id", "INTEGER");
  SealVersion(builders, /*expected_version=*/20u);

  // Version 21.
  builders.sync_entities_metadata->AddColumnToPrimaryKey("storage_key",
                                                         "INTEGER");
  builders.sync_entities_metadata->AddColumn("metadata", "VARCHAR NOT NULL");
  builders.sync_model_metadata->AddColumnToPrimaryKey("id", "INTEGER");
  builders.sync_model_metadata->AddColumn("model_metadata", "VARCHAR NOT NULL");
  SealVersion(builders, /*expected_version=*/21u);

  DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builders.logins->NumberOfColumns())
      << "Adjust LoginDatabaseTableColumns if you change column definitions "
         "here.";
}

// Call this after having called InitializeBuilders(), to migrate the database
// from the current version to kCurrentVersionNumber.
bool MigrateLogins(unsigned current_version,
                   SQLTableBuilders builders,
                   sql::Database* db) {
  if (!builders.logins->MigrateFrom(current_version, db))
    return false;

  if (!builders.sync_entities_metadata->MigrateFrom(current_version, db))
    return false;

  if (!builders.sync_model_metadata->MigrateFrom(current_version, db))
    return false;

  // Data changes, not covered by the schema migration above.
  if (current_version <= 8) {
    sql::Statement fix_time_format;
    fix_time_format.Assign(db->GetCachedStatement(
        SQL_FROM_HERE,
        "UPDATE logins SET date_created = (date_created * ?) + ?"));
    fix_time_format.BindInt64(0, base::Time::kMicrosecondsPerSecond);
    fix_time_format.BindInt64(1, base::Time::kTimeTToMicrosecondsOffset);
    if (!fix_time_format.Run())
      return false;
  }

  if (current_version <= 16) {
    sql::Statement reset_zero_click;
    reset_zero_click.Assign(db->GetCachedStatement(
        SQL_FROM_HERE, "UPDATE logins SET skip_zero_click = 1"));
    if (!reset_zero_click.Run())
      return false;
  }

  return true;
}

// Because of https://crbug.com/295851, some early version numbers might be
// wrong. This function detects that and fixes the version.
bool FixVersionIfNeeded(sql::Database* db, int* current_version) {
  if (*current_version == 1) {
    int extra_columns = 0;
    if (db->DoesColumnExist("logins", "password_type"))
      ++extra_columns;
    if (db->DoesColumnExist("logins", "possible_usernames"))
      ++extra_columns;
    if (extra_columns == 2) {
      *current_version = 2;
    } else if (extra_columns == 1) {
      // If this is https://crbug.com/295851 then either both columns exist
      // or none.
      return false;
    }
  }
  if (*current_version == 2) {
    if (db->DoesColumnExist("logins", "times_used"))
      *current_version = 3;
  }
  if (*current_version == 3) {
    if (db->DoesColumnExist("logins", "form_data"))
      *current_version = 4;
  }
  return true;
}

// Generates the string "(?,?,...,?)" with |count| repetitions of "?".
std::string GeneratePlaceholders(size_t count) {
  std::string result(2 * count + 1, ',');
  result.front() = '(';
  result.back() = ')';
  for (size_t i = 1; i < 2 * count + 1; i += 2) {
    result[i] = '?';
  }
  return result;
}

// Fills |form| with necessary data required to be removed from the database
// and returns it.
PasswordForm GetFormForRemoval(const sql::Statement& statement) {
  PasswordForm form;
  form.origin = GURL(statement.ColumnString(COLUMN_ORIGIN_URL));
  form.username_element = statement.ColumnString16(COLUMN_USERNAME_ELEMENT);
  form.username_value = statement.ColumnString16(COLUMN_USERNAME_VALUE);
  form.password_element = statement.ColumnString16(COLUMN_PASSWORD_ELEMENT);
  form.signon_realm = statement.ColumnString(COLUMN_SIGNON_REALM);
  return form;
}

}  // namespace

LoginDatabase::LoginDatabase(const base::FilePath& db_path)
    : db_path_(db_path) {}

LoginDatabase::~LoginDatabase() {
}

bool LoginDatabase::Init() {
  // Set pragmas for a small, private database (based on WebDatabase).
  db_.set_page_size(2048);
  db_.set_cache_size(32);
  db_.set_exclusive_locking();
  db_.set_histogram_tag("Passwords");

  if (!db_.Open(db_path_)) {
    LogDatabaseInitError(OPEN_FILE_ERROR);
    LOG(ERROR) << "Unable to open the password store database.";
    return false;
  }

  sql::Transaction transaction(&db_);
  if (!transaction.Begin()) {
    LogDatabaseInitError(START_TRANSACTION_ERROR);
    LOG(ERROR) << "Unable to start a transaction.";
    db_.Close();
    return false;
  }

  // Check the database version.
  if (!meta_table_.Init(&db_, kCurrentVersionNumber,
                        kCompatibleVersionNumber)) {
    LogDatabaseInitError(META_TABLE_INIT_ERROR);
    LOG(ERROR) << "Unable to create the meta table.";
    transaction.Rollback();
    db_.Close();
    return false;
  }
  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
    LogDatabaseInitError(INCOMPATIBLE_VERSION);
    LOG(ERROR) << "Password store database is too new, kCurrentVersionNumber="
               << kCurrentVersionNumber << ", GetCompatibleVersionNumber="
               << meta_table_.GetCompatibleVersionNumber();
    transaction.Rollback();
    db_.Close();
    return false;
  }

  SQLTableBuilder logins_builder("logins");
  SQLTableBuilder sync_entities_metadata_builder("sync_entities_metadata");
  SQLTableBuilder sync_model_metadata_builder("sync_model_metadata");
  SQLTableBuilders builders = {&logins_builder, &sync_entities_metadata_builder,
                               &sync_model_metadata_builder};
  InitializeBuilders(builders);
  InitializeStatementStrings(logins_builder);

  if (!db_.DoesTableExist("logins")) {
    if (!logins_builder.CreateTable(&db_)) {
      VLOG(0) << "Failed to create the 'logins' table";
      transaction.Rollback();
      db_.Close();
      return false;
    }
  }

  if (!db_.DoesTableExist("sync_entities_metadata")) {
    if (!sync_entities_metadata_builder.CreateTable(&db_)) {
      VLOG(0) << "Failed to create the 'sync_entities_metadata' table";
      transaction.Rollback();
      db_.Close();
      return false;
    }
  }

  if (!db_.DoesTableExist("sync_model_metadata")) {
    if (!sync_model_metadata_builder.CreateTable(&db_)) {
      VLOG(0) << "Failed to create the 'sync_model_metadata' table";
      transaction.Rollback();
      db_.Close();
      return false;
    }
  }

  stats_table_.Init(&db_);

  int current_version = meta_table_.GetVersionNumber();
  bool migration_success = FixVersionIfNeeded(&db_, &current_version);
  DCHECK_LE(current_version, kCurrentVersionNumber);

  // If the file on disk is an older database version, bring it up to date.
  if (migration_success && current_version < kCurrentVersionNumber) {
    migration_success = MigrateLogins(
        base::checked_cast<unsigned>(current_version), builders, &db_);
  }
  if (migration_success && current_version <= 15) {
    migration_success = stats_table_.MigrateToVersion(16);
  }
  if (migration_success) {
    meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber);
    meta_table_.SetVersionNumber(kCurrentVersionNumber);
  } else {
    LogDatabaseInitError(MIGRATION_ERROR);
    base::UmaHistogramSparse("PasswordManager.LoginDatabaseFailedVersion",
                             meta_table_.GetVersionNumber());
    LOG(ERROR) << "Unable to migrate database from "
               << meta_table_.GetVersionNumber() << " to "
               << kCurrentVersionNumber;
    transaction.Rollback();
    db_.Close();
    return false;
  }

  if (!stats_table_.CreateTableIfNecessary()) {
    LogDatabaseInitError(INIT_STATS_ERROR);
    LOG(ERROR) << "Unable to create the stats table.";
    transaction.Rollback();
    db_.Close();
    return false;
  }

  if (!transaction.Commit()) {
    LogDatabaseInitError(COMMIT_TRANSACTION_ERROR);
    LOG(ERROR) << "Unable to commit a transaction.";
    db_.Close();
    return false;
  }

  LogDatabaseInitError(INIT_OK);
  return true;
}

#if defined(OS_MACOSX) && !defined(OS_IOS)
void LoginDatabase::InitPasswordRecoveryUtil(
    std::unique_ptr<PasswordRecoveryUtilMac> password_recovery_util) {
  password_recovery_util_ = std::move(password_recovery_util);
}
#endif

void LoginDatabase::ReportMetrics(const std::string& sync_username,
                                  bool custom_passphrase_sync_enabled) {
  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE,
      "SELECT signon_realm, password_type, blacklisted_by_user,"
      "COUNT(username_value) FROM logins GROUP BY "
      "signon_realm, password_type, blacklisted_by_user"));

  if (!s.is_valid())
    return;

  std::string custom_passphrase = "WithoutCustomPassphrase";
  if (custom_passphrase_sync_enabled) {
    custom_passphrase = "WithCustomPassphrase";
  }

  int total_user_created_accounts = 0;
  int total_generated_accounts = 0;
  int blacklisted_sites = 0;
  while (s.Step()) {
    PasswordForm::Type password_type =
        static_cast<PasswordForm::Type>(s.ColumnInt(1));
    int blacklisted = s.ColumnInt(2);
    int accounts_per_site = s.ColumnInt(3);
    if (blacklisted) {
      ++blacklisted_sites;
    } else if (password_type == PasswordForm::TYPE_GENERATED) {
      total_generated_accounts += accounts_per_site;
      LogAccountStat(
          base::StringPrintf("PasswordManager.AccountsPerSite.AutoGenerated.%s",
                             custom_passphrase.c_str()),
          accounts_per_site);
    } else {
      total_user_created_accounts += accounts_per_site;
      LogAccountStat(
          base::StringPrintf("PasswordManager.AccountsPerSite.UserCreated.%s",
                             custom_passphrase.c_str()),
          accounts_per_site);
    }
  }
  LogAccountStat(
      base::StringPrintf("PasswordManager.TotalAccounts.UserCreated.%s",
                         custom_passphrase.c_str()),
      total_user_created_accounts);
  LogAccountStat(
      base::StringPrintf("PasswordManager.TotalAccounts.AutoGenerated.%s",
                         custom_passphrase.c_str()),
      total_generated_accounts);
  LogAccountStat(base::StringPrintf("PasswordManager.BlacklistedSites.%s",
                                    custom_passphrase.c_str()),
                 blacklisted_sites);

  sql::Statement usage_statement(db_.GetCachedStatement(
      SQL_FROM_HERE, "SELECT password_type, times_used FROM logins"));

  if (!usage_statement.is_valid())
    return;

  while (usage_statement.Step()) {
    PasswordForm::Type type =
        static_cast<PasswordForm::Type>(usage_statement.ColumnInt(0));

    if (type == PasswordForm::TYPE_GENERATED) {
      LogTimesUsedStat(base::StringPrintf(
                           "PasswordManager.TimesPasswordUsed.AutoGenerated.%s",
                           custom_passphrase.c_str()),
                       usage_statement.ColumnInt(1));
    } else {
      LogTimesUsedStat(
          base::StringPrintf("PasswordManager.TimesPasswordUsed.UserCreated.%s",
                             custom_passphrase.c_str()),
          usage_statement.ColumnInt(1));
    }
  }

  bool syncing_account_saved = false;
  if (!sync_username.empty()) {
    sql::Statement sync_statement(db_.GetCachedStatement(
        SQL_FROM_HERE,
        "SELECT username_value FROM logins "
        "WHERE signon_realm == ?"));
    sync_statement.BindString(
        0, GaiaUrls::GetInstance()->gaia_url().GetOrigin().spec());

    if (!sync_statement.is_valid())
      return;

    while (sync_statement.Step()) {
      std::string username = sync_statement.ColumnString(0);
      if (gaia::AreEmailsSame(sync_username, username)) {
        syncing_account_saved = true;
        break;
      }
    }
  }
  UMA_HISTOGRAM_ENUMERATION("PasswordManager.SyncingAccountState",
                            2 * sync_username.empty() + syncing_account_saved,
                            4);

  sql::Statement empty_usernames_statement(db_.GetCachedStatement(
      SQL_FROM_HERE, "SELECT COUNT(*) FROM logins "
                     "WHERE blacklisted_by_user=0 AND username_value=''"));
  if (empty_usernames_statement.Step()) {
    int empty_forms = empty_usernames_statement.ColumnInt(0);
    UMA_HISTOGRAM_COUNTS_100("PasswordManager.EmptyUsernames.CountInDatabase",
                             empty_forms);
  }

  sql::Statement standalone_empty_usernames_statement(db_.GetCachedStatement(
      SQL_FROM_HERE, "SELECT COUNT(*) FROM logins a "
                     "WHERE a.blacklisted_by_user=0 AND a.username_value='' "
                     "AND NOT EXISTS (SELECT * FROM logins b "
                     "WHERE b.blacklisted_by_user=0 AND b.username_value!='' "
                     "AND a.signon_realm = b.signon_realm)"));
  if (standalone_empty_usernames_statement.Step()) {
    int num_entries = standalone_empty_usernames_statement.ColumnInt(0);
    UMA_HISTOGRAM_COUNTS_100(
        "PasswordManager.EmptyUsernames.WithoutCorrespondingNonempty",
        num_entries);
  }

  sql::Statement logins_with_schemes_statement(db_.GetUniqueStatement(
      "SELECT signon_realm, origin_url, blacklisted_by_user FROM logins;"));

  if (!logins_with_schemes_statement.is_valid())
    return;

  int android_logins = 0;
  int ftp_logins = 0;
  int http_logins = 0;
  int https_logins = 0;
  int other_logins = 0;

  while (logins_with_schemes_statement.Step()) {
    std::string signon_realm = logins_with_schemes_statement.ColumnString(0);
    GURL origin_url = GURL(logins_with_schemes_statement.ColumnString(1));
    bool blacklisted_by_user = !!logins_with_schemes_statement.ColumnInt(2);
    if (blacklisted_by_user)
      continue;

    if (IsValidAndroidFacetURI(signon_realm)) {
      ++android_logins;
    } else if (origin_url.SchemeIs(url::kHttpsScheme)) {
      ++https_logins;
    } else if (origin_url.SchemeIs(url::kHttpScheme)) {
      ++http_logins;
    } else if (origin_url.SchemeIs(url::kFtpScheme)) {
      ++ftp_logins;
    } else {
      ++other_logins;
    }
  }

  LogNumberOfAccountsForScheme("Android", android_logins);
  LogNumberOfAccountsForScheme("Ftp", ftp_logins);
  LogNumberOfAccountsForScheme("Http", http_logins);
  LogNumberOfAccountsForScheme("Https", https_logins);
  LogNumberOfAccountsForScheme("Other", other_logins);

  sql::Statement saved_passwords_statement(
      db_.GetUniqueStatement("SELECT signon_realm, password_value, scheme "
                             "FROM logins WHERE blacklisted_by_user = 0"));

  std::map<base::string16, std::vector<std::string>> passwords_to_realms;
  size_t failed_encryption = 0;
  while (saved_passwords_statement.Step()) {
    base::string16 decrypted_password;
    // Note that CryptProtectData() is non-deterministic, so passwords must be
    // decrypted before checking equality.
    if (DecryptedString(saved_passwords_statement.ColumnString(1),
                        &decrypted_password) == ENCRYPTION_RESULT_SUCCESS) {
      std::string signon_realm = saved_passwords_statement.ColumnString(0);
      if (saved_passwords_statement.ColumnInt(2) == 0 &&
          !decrypted_password.empty() &&
          !IsValidAndroidFacetURI(signon_realm)) {
        passwords_to_realms[decrypted_password].push_back(
            std::move(signon_realm));
      }
    } else {
      ++failed_encryption;
    }
  }
  UMA_HISTOGRAM_COUNTS_100("PasswordManager.InaccessiblePasswords",
                           failed_encryption);

  for (const auto& password_to_realms : passwords_to_realms)
    LogPasswordReuseMetrics(password_to_realms.second);
}

PasswordStoreChangeList LoginDatabase::AddLogin(const PasswordForm& form) {
  PasswordStoreChangeList list;
  if (form.blacklisted_by_user) {
    sql::Statement blacklist_statement(db_.GetUniqueStatement(
        "SELECT EXISTS(SELECT 1 FROM logins WHERE signon_realm == ? AND "
        "blacklisted_by_user == 1)"));
    blacklist_statement.BindString(0, form.signon_realm);
    const bool is_already_blacklisted =
        blacklist_statement.Step() && blacklist_statement.ColumnBool(0);
    UMA_HISTOGRAM_BOOLEAN(
        "PasswordManager.BlacklistedSites.PreventedAddingDuplicates",
        is_already_blacklisted);
    if (is_already_blacklisted) {
      // The site is already blacklisted, so we need to ignore the request to
      // avoid duplicates.
      return list;
    }
  }
  if (!DoesMatchConstraints(form))
    return list;
  std::string encrypted_password;
  if (EncryptedString(form.password_value, &encrypted_password) !=
      ENCRYPTION_RESULT_SUCCESS)
    return list;

  DCHECK(!add_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, add_statement_.c_str()));
  BindAddStatement(form, encrypted_password, &s);
  db_.set_error_callback(base::Bind(&AddCallback));
  const bool success = s.Run();
  db_.reset_error_callback();
  if (success) {
    list.emplace_back(PasswordStoreChange::ADD, form, db_.GetLastInsertRowId());
    return list;
  }
  // Repeat the same statement but with REPLACE semantic.
  DCHECK(!add_replace_statement_.empty());
  int old_primary_key = GetPrimaryKey(form);
  s.Assign(
      db_.GetCachedStatement(SQL_FROM_HERE, add_replace_statement_.c_str()));
  BindAddStatement(form, encrypted_password, &s);
  if (s.Run()) {
    list.emplace_back(PasswordStoreChange::REMOVE, form, old_primary_key);
    list.emplace_back(PasswordStoreChange::ADD, form, db_.GetLastInsertRowId());
  }
  return list;
}

PasswordStoreChangeList LoginDatabase::AddBlacklistedLoginForTesting(
    const PasswordForm& form) {
  DCHECK(form.blacklisted_by_user);
  PasswordStoreChangeList list;

  std::string encrypted_password;
  if (EncryptedString(form.password_value, &encrypted_password) !=
      ENCRYPTION_RESULT_SUCCESS)
    return list;

  DCHECK(!add_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, add_statement_.c_str()));
  BindAddStatement(form, encrypted_password, &s);
  if (s.Run())
    list.emplace_back(PasswordStoreChange::ADD, form, db_.GetLastInsertRowId());
  return list;
}

PasswordStoreChangeList LoginDatabase::UpdateLogin(const PasswordForm& form) {
  std::string encrypted_password;
  if (EncryptedString(form.password_value, &encrypted_password) !=
      ENCRYPTION_RESULT_SUCCESS)
    return PasswordStoreChangeList();

#if defined(OS_IOS)
  DeleteEncryptedPassword(form);
#endif
  // Replacement is necessary to deal with updating imported credentials. See
  // crbug.com/349138 for details.
  DCHECK(!update_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, update_statement_.c_str()));
  int next_param = 0;
  s.BindString(next_param++, form.action.spec());
  s.BindBlob(next_param++, encrypted_password.data(),
             static_cast<int>(encrypted_password.length()));
  s.BindString16(next_param++, form.submit_element);
  s.BindInt(next_param++, form.preferred);
  s.BindInt64(next_param++, form.date_created.ToInternalValue());
  s.BindInt(next_param++, form.blacklisted_by_user);
  s.BindInt(next_param++, form.scheme);
  s.BindInt(next_param++, form.type);
  s.BindInt(next_param++, form.times_used);
  base::Pickle form_data_pickle;
  autofill::SerializeFormData(form.form_data, &form_data_pickle);
  s.BindBlob(next_param++, form_data_pickle.data(), form_data_pickle.size());
  s.BindInt64(next_param++, form.date_synced.ToInternalValue());
  s.BindString16(next_param++, form.display_name);
  s.BindString(next_param++, form.icon_url.spec());
  // An empty Origin serializes as "null" which would be strange to store here.
  s.BindString(next_param++, form.federation_origin.opaque()
                                 ? std::string()
                                 : form.federation_origin.Serialize());
  s.BindInt(next_param++, form.skip_zero_click);
  s.BindInt(next_param++, form.generation_upload_status);
  base::Pickle username_pickle =
      SerializeValueElementPairs(form.other_possible_usernames);
  s.BindBlob(next_param++, username_pickle.data(), username_pickle.size());
  // NOTE: Add new fields here unless the field is a part of the unique key.
  // If so, add new field below.

  // WHERE starts here.
  s.BindString(next_param++, form.origin.spec());
  s.BindString16(next_param++, form.username_element);
  s.BindString16(next_param++, form.username_value);
  s.BindString16(next_param++, form.password_element);
  s.BindString(next_param++, form.signon_realm);
  // NOTE: Add new fields here only if the field is a part of the unique key.
  // Otherwise, add the field above "WHERE starts here" comment.

  if (!s.Run())
    return PasswordStoreChangeList();

  PasswordStoreChangeList list;
  if (db_.GetLastChangeCount())
    list.emplace_back(PasswordStoreChange::UPDATE, form, GetPrimaryKey(form));

  return list;
}

bool LoginDatabase::RemoveLogin(const PasswordForm& form,
                                PasswordStoreChangeList* changes) {
  if (changes) {
    changes->clear();
  }
  if (form.is_public_suffix_match) {
    // TODO(dvadym): Discuss whether we should allow to remove PSL matched
    // credentials.
    return false;
  }
#if defined(OS_IOS)
  DeleteEncryptedPassword(form);
#endif
  // Remove a login by UNIQUE-constrained fields.
  DCHECK(!delete_statement_.empty());
  int primary_key = GetPrimaryKey(form);
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, delete_statement_.c_str()));
  s.BindString(0, form.origin.spec());
  s.BindString16(1, form.username_element);
  s.BindString16(2, form.username_value);
  s.BindString16(3, form.password_element);
  s.BindString(4, form.signon_realm);

  if (!s.Run() || db_.GetLastChangeCount() == 0) {
    return false;
  }
  if (changes) {
    changes->emplace_back(PasswordStoreChange::REMOVE, form, primary_key);
  }
  return true;
}

bool LoginDatabase::RemoveLoginById(int id) {
#if defined(OS_IOS)
  DeleteEncryptedPasswordById(id);
#endif
  DCHECK(!delete_by_id_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, delete_by_id_statement_.c_str()));
  s.BindInt(0, id);
  return s.Run() && db_.GetLastChangeCount() > 0;
}

bool LoginDatabase::RemoveLoginsCreatedBetween(
    base::Time delete_begin,
    base::Time delete_end,
    PasswordStoreChangeList* changes) {
  if (changes) {
    changes->clear();
  }
  PrimaryKeyToFormMap key_to_form_map;
  ScopedTransaction transaction(this);
  if (!GetLoginsCreatedBetween(delete_begin, delete_end, &key_to_form_map)) {
    return false;
  }

#if defined(OS_IOS)
  for (const auto& pair : key_to_form_map) {
    DeleteEncryptedPassword(*pair.second);
  }
#endif

  sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
      "DELETE FROM logins WHERE "
      "date_created >= ? AND date_created < ?"));
  s.BindInt64(0, delete_begin.ToInternalValue());
  s.BindInt64(1, delete_end.is_null() ? std::numeric_limits<int64_t>::max()
                                      : delete_end.ToInternalValue());

  if (!s.Run()) {
    return false;
  }
  if (changes) {
    for (const auto& pair : key_to_form_map) {
      changes->emplace_back(PasswordStoreChange::REMOVE,
                            /*form=*/std::move(*pair.second),
                            /*primary_key=*/pair.first);
    }
  }
  return true;
}

bool LoginDatabase::RemoveLoginsSyncedBetween(
    base::Time delete_begin,
    base::Time delete_end,
    PasswordStoreChangeList* changes) {
  if (changes) {
    changes->clear();
  }
  ScopedTransaction transaction(this);
  PrimaryKeyToFormMap key_to_form_map;
  if (!GetLoginsSyncedBetween(delete_begin, delete_end, &key_to_form_map)) {
    return false;
  }

#if defined(OS_IOS)
  for (const auto& pair : key_to_form_map) {
    DeleteEncryptedPassword(*pair.second);
  }
#endif

  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE,
      "DELETE FROM logins WHERE date_synced >= ? AND date_synced < ?"));
  s.BindInt64(0, delete_begin.ToInternalValue());
  s.BindInt64(1,
              delete_end.is_null() ? base::Time::Max().ToInternalValue()
                                   : delete_end.ToInternalValue());

  if (!s.Run()) {
    return false;
  }
  if (changes) {
    for (const auto& pair : key_to_form_map) {
      changes->emplace_back(PasswordStoreChange::REMOVE,
                            /*form=*/std::move(*pair.second),
                            /*primary_key=*/pair.first);
    }
  }
  return true;
}

bool LoginDatabase::GetAutoSignInLogins(
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  DCHECK(forms);
  DCHECK(!autosignin_statement_.empty());
  forms->clear();

  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, autosignin_statement_.c_str()));
  PrimaryKeyToFormMap key_to_form_map;
  bool result = StatementToForms(&s, nullptr, &key_to_form_map);
  for (auto& pair : key_to_form_map) {
    forms->push_back(std::move(pair.second));
  }
  return result;
}

bool LoginDatabase::DisableAutoSignInForOrigin(const GURL& origin) {
  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE,
      "UPDATE logins SET skip_zero_click = 1 WHERE origin_url = ?;"));
  s.BindString(0, origin.spec());

  return s.Run();
}

LoginDatabase::EncryptionResult LoginDatabase::InitPasswordFormFromStatement(
    const sql::Statement& s,
    int* primary_key,
    PasswordForm* form) const {
  std::string encrypted_password;
  s.ColumnBlobAsString(COLUMN_PASSWORD_VALUE, &encrypted_password);
  base::string16 decrypted_password;
  EncryptionResult encryption_result =
      DecryptedString(encrypted_password, &decrypted_password);
  if (encryption_result != ENCRYPTION_RESULT_SUCCESS) {
    VLOG(0) << "Password decryption failed, encryption_result is "
            << encryption_result;
    return encryption_result;
  }

  *primary_key = s.ColumnInt(COLUMN_ID);
  std::string tmp = s.ColumnString(COLUMN_ORIGIN_URL);
  form->origin = GURL(tmp);
  tmp = s.ColumnString(COLUMN_ACTION_URL);
  form->action = GURL(tmp);
  form->username_element = s.ColumnString16(COLUMN_USERNAME_ELEMENT);
  form->username_value = s.ColumnString16(COLUMN_USERNAME_VALUE);
  form->password_element = s.ColumnString16(COLUMN_PASSWORD_ELEMENT);
  form->password_value = decrypted_password;
  form->submit_element = s.ColumnString16(COLUMN_SUBMIT_ELEMENT);
  tmp = s.ColumnString(COLUMN_SIGNON_REALM);
  form->signon_realm = tmp;
  form->preferred = (s.ColumnInt(COLUMN_PREFERRED) > 0);
  form->date_created =
      base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED));
  form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0);
  int scheme_int = s.ColumnInt(COLUMN_SCHEME);
  DCHECK_LE(0, scheme_int);
  DCHECK_GE(PasswordForm::SCHEME_LAST, scheme_int);
  form->scheme = static_cast<PasswordForm::Scheme>(scheme_int);
  int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE);
  DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_LAST) << type_int;
  form->type = static_cast<PasswordForm::Type>(type_int);
  if (s.ColumnByteLength(COLUMN_POSSIBLE_USERNAME_PAIRS)) {
    base::Pickle pickle(
        static_cast<const char*>(s.ColumnBlob(COLUMN_POSSIBLE_USERNAME_PAIRS)),
        s.ColumnByteLength(COLUMN_POSSIBLE_USERNAME_PAIRS));
    form->other_possible_usernames = DeserializeValueElementPairs(pickle);
  }
  form->times_used = s.ColumnInt(COLUMN_TIMES_USED);
  if (s.ColumnByteLength(COLUMN_FORM_DATA)) {
    base::Pickle form_data_pickle(
        static_cast<const char*>(s.ColumnBlob(COLUMN_FORM_DATA)),
        s.ColumnByteLength(COLUMN_FORM_DATA));
    base::PickleIterator form_data_iter(form_data_pickle);
    bool success =
        autofill::DeserializeFormData(&form_data_iter, &form->form_data);
    metrics_util::FormDeserializationStatus status =
        success ? metrics_util::LOGIN_DATABASE_SUCCESS
                : metrics_util::LOGIN_DATABASE_FAILURE;
    metrics_util::LogFormDataDeserializationStatus(status);
  }
  form->date_synced =
      base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_SYNCED));
  form->display_name = s.ColumnString16(COLUMN_DISPLAY_NAME);
  form->icon_url = GURL(s.ColumnString(COLUMN_ICON_URL));
  form->federation_origin =
      url::Origin::Create(GURL(s.ColumnString(COLUMN_FEDERATION_URL)));
  form->skip_zero_click = (s.ColumnInt(COLUMN_SKIP_ZERO_CLICK) > 0);
  int generation_upload_status_int =
      s.ColumnInt(COLUMN_GENERATION_UPLOAD_STATUS);
  DCHECK(generation_upload_status_int >= 0 &&
         generation_upload_status_int <= PasswordForm::UNKNOWN_STATUS);
  form->generation_upload_status =
      static_cast<PasswordForm::GenerationUploadStatus>(
          generation_upload_status_int);
  return ENCRYPTION_RESULT_SUCCESS;
}

bool LoginDatabase::GetLogins(
    const PasswordStore::FormDigest& form,
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  DCHECK(forms);
  forms->clear();

  const GURL signon_realm(form.signon_realm);
  std::string registered_domain = GetRegistryControlledDomain(signon_realm);
  const bool should_PSL_matching_apply =
      form.scheme == PasswordForm::SCHEME_HTML &&
      ShouldPSLDomainMatchingApply(registered_domain);
  const bool should_federated_apply = form.scheme == PasswordForm::SCHEME_HTML;
  DCHECK(!get_statement_.empty());
  DCHECK(!get_statement_psl_.empty());
  DCHECK(!get_statement_federated_.empty());
  DCHECK(!get_statement_psl_federated_.empty());
  const std::string* sql_query = &get_statement_;
  if (should_PSL_matching_apply && should_federated_apply)
    sql_query = &get_statement_psl_federated_;
  else if (should_PSL_matching_apply)
    sql_query = &get_statement_psl_;
  else if (should_federated_apply)
    sql_query = &get_statement_federated_;

  // TODO(nyquist) Consider usage of GetCachedStatement when
  // http://crbug.com/248608 is fixed.
  sql::Statement s(db_.GetUniqueStatement(sql_query->c_str()));
  s.BindString(0, form.signon_realm);
  int placeholder = 1;

  // PSL matching only applies to HTML forms.
  if (should_PSL_matching_apply) {
    // We are extending the original SQL query with one that includes more
    // possible matches based on public suffix domain matching. Using a regexp
    // here is just an optimization to not have to parse all the stored entries
    // in the |logins| table. The result (scheme, domain and port) is verified
    // further down using GURL. See the functions SchemeMatches,
    // RegistryControlledDomainMatches and PortMatches.
    // We need to escape . in the domain. Since the domain has already been
    // sanitized using GURL, we do not need to escape any other characters.
    base::ReplaceChars(registered_domain, ".", "\\.", &registered_domain);
    std::string scheme = signon_realm.scheme();
    // We need to escape . in the scheme. Since the scheme has already been
    // sanitized using GURL, we do not need to escape any other characters.
    // The scheme soap.beep is an example with '.'.
    base::ReplaceChars(scheme, ".", "\\.", &scheme);
    const std::string port = signon_realm.port();
    // For a signon realm such as http://foo.bar/, this regexp will match
    // domains on the form http://foo.bar/, http://www.foo.bar/,
    // http://www.mobile.foo.bar/. It will not match http://notfoo.bar/.
    // The scheme and port has to be the same as the observed form.
    std::string regexp = "^(" + scheme + ":\\/\\/)([\\w-]+\\.)*" +
                         registered_domain + "(:" + port + ")?\\/$";
    s.BindString(placeholder++, regexp);

    if (should_federated_apply) {
      // This regex matches any subdomain of |registered_domain|, in particular
      // it matches the empty subdomain. Hence exact domain matches are also
      // retrieved.
      s.BindString(placeholder++,
                   "^federation://([\\w-]+\\.)*" + registered_domain + "/.+$");
    }
  } else if (should_federated_apply) {
    std::string expression =
        base::StringPrintf("federation://%s/%%", form.origin.host().c_str());
    s.BindString(placeholder++, expression);
  }

  if (!should_PSL_matching_apply && !should_federated_apply) {
    // Otherwise the histogram is reported in StatementToForms.
    UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering",
                              PSL_DOMAIN_MATCH_NOT_USED,
                              PSL_DOMAIN_MATCH_COUNT);
  }
  PrimaryKeyToFormMap key_to_form_map;
  bool success = StatementToForms(
      &s, should_PSL_matching_apply || should_federated_apply ? &form : nullptr,
      &key_to_form_map);
  if (!success) {
    return false;
  }
  for (auto& pair : key_to_form_map) {
    forms->push_back(std::move(pair.second));
  }
  return true;
}

bool LoginDatabase::GetLoginsForSameOrganizationName(
    const std::string& signon_realm,
    std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) {
  DCHECK(forms);
  forms->clear();

  GURL signon_realm_as_url(signon_realm);
  if (!signon_realm_as_url.SchemeIsHTTPOrHTTPS())
    return true;

  std::string organization_name =
      GetOrganizationIdentifyingName(signon_realm_as_url);
  if (organization_name.empty())
    return true;

  // SQLite does not provide a function to escape special characters, but
  // seemingly uses POSIX Extended Regular Expressions (ERE), and so does RE2.
  // In the worst case the bogus results will be filtered out below.
  static constexpr char kRESchemeAndSubdomains[] = "^https?://([\\w+%-]+\\.)*";
  static constexpr char kREDotAndEffectiveTLD[] = "(\\.[\\w+%-]+)+/$";
  const std::string signon_realms_with_same_organization_name_regexp =
      kRESchemeAndSubdomains + RE2::QuoteMeta(organization_name) +
      kREDotAndEffectiveTLD;
  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE, get_same_organization_name_logins_statement_.c_str()));
  s.BindString(0, signon_realms_with_same_organization_name_regexp);

  PrimaryKeyToFormMap key_to_form_map;
  bool success = StatementToForms(&s, nullptr, &key_to_form_map);
  for (auto& pair : key_to_form_map) {
    forms->push_back(std::move(pair.second));
  }

  using PasswordFormPtr = std::unique_ptr<autofill::PasswordForm>;
  base::EraseIf(*forms, [&organization_name](const PasswordFormPtr& form) {
    GURL candidate_signon_realm_as_url(form->signon_realm);
    DCHECK_EQ(form->scheme, PasswordForm::SCHEME_HTML);
    DCHECK(candidate_signon_realm_as_url.SchemeIsHTTPOrHTTPS());
    std::string candidate_form_organization_name =
        GetOrganizationIdentifyingName(candidate_signon_realm_as_url);
    return candidate_form_organization_name != organization_name;
  });

  return success;
}

bool LoginDatabase::GetLoginsCreatedBetween(
    const base::Time begin,
    const base::Time end,
    PrimaryKeyToFormMap* key_to_form_map) {
  DCHECK(key_to_form_map);
  DCHECK(!created_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, created_statement_.c_str()));
  s.BindInt64(0, begin.ToInternalValue());
  s.BindInt64(1, end.is_null() ? std::numeric_limits<int64_t>::max()
                               : end.ToInternalValue());

  return StatementToForms(&s, nullptr, key_to_form_map);
}

bool LoginDatabase::GetLoginsSyncedBetween(
    const base::Time begin,
    const base::Time end,
    PrimaryKeyToFormMap* key_to_form_map) {
  DCHECK(key_to_form_map);
  DCHECK(!synced_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, synced_statement_.c_str()));
  s.BindInt64(0, begin.ToInternalValue());
  s.BindInt64(1,
              end.is_null() ? base::Time::Max().ToInternalValue()
                            : end.ToInternalValue());

  return StatementToForms(&s, nullptr, key_to_form_map);
}

bool LoginDatabase::GetAutofillableLogins(
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  return GetAllLoginsWithBlacklistSetting(false, forms);
}

bool LoginDatabase::GetBlacklistLogins(
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  return GetAllLoginsWithBlacklistSetting(true, forms);
}

bool LoginDatabase::GetAllLoginsWithBlacklistSetting(
    bool blacklisted,
    std::vector<std::unique_ptr<PasswordForm>>* forms) {
  DCHECK(forms);
  DCHECK(!blacklisted_statement_.empty());
  forms->clear();

  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, blacklisted_statement_.c_str()));
  s.BindInt(0, blacklisted ? 1 : 0);

  PrimaryKeyToFormMap key_to_form_map;

  if (!StatementToForms(&s, nullptr, &key_to_form_map)) {
    return false;
  }

  for (auto& pair : key_to_form_map) {
    forms->push_back(std::move(pair.second));
  }
  return true;
}

bool LoginDatabase::DeleteAndRecreateDatabaseFile() {
  DCHECK(db_.is_open());
  meta_table_.Reset();
  db_.Close();
  sql::Database::Delete(db_path_);
  return Init();
}

DatabaseCleanupResult LoginDatabase::DeleteUndecryptableLogins() {
#if defined(OS_MACOSX) && !defined(OS_IOS)
  // If the Keychain is unavailable, don't delete any logins.
  if (!OSCrypt::IsEncryptionAvailable()) {
    metrics_util::LogDeleteUndecryptableLoginsReturnValue(
        metrics_util::DeleteCorruptedPasswordsResult::kEncryptionUnavailable);
    return DatabaseCleanupResult::kEncryptionUnavailable;
  }

  DCHECK(db_.is_open());

  // Get all autofillable (not blacklisted) logins.
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, blacklisted_statement_.c_str()));
  s.BindInt(0, 0);  // blacklisted = false

  std::vector<PasswordForm> forms_to_be_deleted;

  while (s.Step()) {
    std::string encrypted_password;
    s.ColumnBlobAsString(COLUMN_PASSWORD_VALUE, &encrypted_password);
    base::string16 decrypted_password;
    if (DecryptedString(encrypted_password, &decrypted_password) ==
        ENCRYPTION_RESULT_SUCCESS)
      continue;

    // If it was not possible to decrypt the password, remove it from the
    // database.
    forms_to_be_deleted.push_back(GetFormForRemoval(s));
  }

  for (const auto& form : forms_to_be_deleted) {
    if (!RemoveLogin(form, nullptr)) {
      metrics_util::LogDeleteUndecryptableLoginsReturnValue(
          metrics_util::DeleteCorruptedPasswordsResult::kItemFailure);
      return DatabaseCleanupResult::kItemFailure;
    }
  }

  if (forms_to_be_deleted.empty()) {
    metrics_util::LogDeleteUndecryptableLoginsReturnValue(
        metrics_util::DeleteCorruptedPasswordsResult::kSuccessNoDeletions);
  } else {
    DCHECK(password_recovery_util_);
    password_recovery_util_->RecordPasswordRecovery();
    metrics_util::LogDeleteUndecryptableLoginsReturnValue(
        metrics_util::DeleteCorruptedPasswordsResult::kSuccessPasswordsDeleted);
    UMA_HISTOGRAM_COUNTS_100("PasswordManager.CleanedUpPasswords",
                             forms_to_be_deleted.size());
  }
#endif

  return DatabaseCleanupResult::kSuccess;
}

std::string LoginDatabase::GetEncryptedPassword(
    const PasswordForm& form) const {
  DCHECK(!encrypted_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, encrypted_statement_.c_str()));

  s.BindString(0, form.origin.spec());
  s.BindString16(1, form.username_element);
  s.BindString16(2, form.username_value);
  s.BindString16(3, form.password_element);
  s.BindString(4, form.signon_realm);

  std::string encrypted_password;
  if (s.Step()) {
    s.ColumnBlobAsString(0, &encrypted_password);
  }
  return encrypted_password;
}

bool LoginDatabase::UpdateSyncMetadata(
    syncer::ModelType model_type,
    const std::string& storage_key,
    const sync_pb::EntityMetadata& metadata) {
  DCHECK_EQ(model_type, syncer::PASSWORDS);

  int storage_key_int = 0;
  if (!base::StringToInt(storage_key, &storage_key_int)) {
    DLOG(ERROR) << "Invalid storage key. Failed to convert the storage key to "
                   "an integer.";
    return false;
  }

  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE,
                             "INSERT OR REPLACE INTO sync_entities_metadata "
                             "(storage_key, metadata) VALUES(?, ?)"));

  s.BindInt(0, storage_key_int);
  s.BindString(1, metadata.SerializeAsString());

  return s.Run();
}

bool LoginDatabase::ClearSyncMetadata(syncer::ModelType model_type,
                                      const std::string& storage_key) {
  DCHECK_EQ(model_type, syncer::PASSWORDS);

  int storage_key_int = 0;
  if (!base::StringToInt(storage_key, &storage_key_int)) {
    DLOG(ERROR) << "Invalid storage key. Failed to convert the storage key to "
                   "an integer.";
    return false;
  }

  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE,
                             "DELETE FROM sync_entities_metadata WHERE "
                             "storage_key=?"));
  s.BindInt(0, storage_key_int);

  return s.Run();
}

bool LoginDatabase::UpdateModelTypeState(
    syncer::ModelType model_type,
    const sync_pb::ModelTypeState& model_type_state) {
  DCHECK_EQ(model_type, syncer::PASSWORDS);

  // Make sure only one row is left by storing it in the entry with id=1
  // every time.
  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE,
      "INSERT OR REPLACE INTO sync_model_metadata (id, model_metadata) "
      "VALUES(1, ?)"));
  s.BindString(0, model_type_state.SerializeAsString());

  return s.Run();
}

bool LoginDatabase::ClearModelTypeState(syncer::ModelType model_type) {
  DCHECK_EQ(model_type, syncer::PASSWORDS);

  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE, "DELETE FROM sync_model_metadata WHERE id=1"));

  return s.Run();
}

bool LoginDatabase::BeginTransaction() {
  return db_.BeginTransaction();
}

bool LoginDatabase::CommitTransaction() {
  return db_.CommitTransaction();
}

int LoginDatabase::GetPrimaryKey(const PasswordForm& form) const {
  DCHECK(!id_statement_.empty());
  sql::Statement s(
      db_.GetCachedStatement(SQL_FROM_HERE, id_statement_.c_str()));

  s.BindString(0, form.origin.spec());
  s.BindString16(1, form.username_element);
  s.BindString16(2, form.username_value);
  s.BindString16(3, form.password_element);
  s.BindString(4, form.signon_realm);

  if (s.Step()) {
    return s.ColumnInt(0);
  }
  return -1;
}

std::unique_ptr<syncer::MetadataBatch>
LoginDatabase::GetAllSyncMetadataForTesting() {
  std::unique_ptr<syncer::MetadataBatch> metadata_batch =
      GetAllSyncEntityMetadataForTesting();
  if (metadata_batch == nullptr) {
    return nullptr;
  }

  std::unique_ptr<sync_pb::ModelTypeState> model_type_state =
      GetModelTypeStateForTesting();
  if (model_type_state == nullptr) {
    return nullptr;
  }

  metadata_batch->SetModelTypeState(*model_type_state);
  return metadata_batch;
}

std::unique_ptr<syncer::MetadataBatch>
LoginDatabase::GetAllSyncEntityMetadataForTesting() {
  auto metadata_batch = std::make_unique<syncer::MetadataBatch>();
  sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
                                          "SELECT storage_key, metadata FROM "
                                          "sync_entities_metadata"));

  while (s.Step()) {
    std::string storage_key = s.ColumnString(0);
    std::string serialized_metadata = s.ColumnString(1);
    sync_pb::EntityMetadata entity_metadata;
    if (entity_metadata.ParseFromString(serialized_metadata)) {
      metadata_batch->AddMetadata(storage_key, entity_metadata);
    } else {
      DLOG(WARNING) << "Failed to deserialize PASSWORD model type "
                       "sync_pb::EntityMetadata.";
      return nullptr;
    }
  }
  if (!s.Succeeded()) {
    return nullptr;
  }
  return metadata_batch;
}

std::unique_ptr<sync_pb::ModelTypeState>
LoginDatabase::GetModelTypeStateForTesting() {
  auto state = std::make_unique<sync_pb::ModelTypeState>();
  sql::Statement s(db_.GetCachedStatement(
      SQL_FROM_HERE,
      "SELECT model_metadata FROM sync_model_metadata WHERE id=1"));

  if (!s.Step()) {
    if (s.Succeeded())
      return state;
    else
      return nullptr;
  }

  std::string serialized_state = s.ColumnString(0);
  if (state->ParseFromString(serialized_state)) {
    return state;
  }
  return nullptr;
}

bool LoginDatabase::StatementToForms(
    sql::Statement* statement,
    const PasswordStore::FormDigest* matched_form,
    PrimaryKeyToFormMap* key_to_form_map) {
  PSLDomainMatchMetric psl_domain_match_metric = PSL_DOMAIN_MATCH_NONE;

  std::vector<PasswordForm> forms_to_be_deleted;

  key_to_form_map->clear();
  while (statement->Step()) {
    auto new_form = std::make_unique<PasswordForm>();
    int primary_key = -1;
    EncryptionResult result =
        InitPasswordFormFromStatement(*statement, &primary_key, new_form.get());
    if (result == ENCRYPTION_RESULT_SERVICE_FAILURE)
      return false;
    if (result == ENCRYPTION_RESULT_ITEM_FAILURE) {
      if (IsUsingCleanupMechanism())
        forms_to_be_deleted.push_back(GetFormForRemoval(*statement));
      continue;
    }
    DCHECK_EQ(ENCRYPTION_RESULT_SUCCESS, result);

    if (matched_form) {
      switch (GetMatchResult(*new_form, *matched_form)) {
        case MatchResult::NO_MATCH:
          continue;
        case MatchResult::EXACT_MATCH:
          break;
        case MatchResult::PSL_MATCH:
          psl_domain_match_metric = PSL_DOMAIN_MATCH_FOUND;
          new_form->is_public_suffix_match = true;
          break;
        case MatchResult::FEDERATED_MATCH:
          break;
        case MatchResult::FEDERATED_PSL_MATCH:
          psl_domain_match_metric = PSL_DOMAIN_MATCH_FOUND_FEDERATED;
          new_form->is_public_suffix_match = true;
          break;
      }
    }

    key_to_form_map->emplace(primary_key, std::move(new_form));
  }

  if (matched_form) {
    UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering",
                              psl_domain_match_metric, PSL_DOMAIN_MATCH_COUNT);
  }

#if defined(OS_MACOSX) && !defined(OS_IOS)
  // Remove corrupted passwords.
  size_t count_removed_logins = 0;
  for (const auto& form : forms_to_be_deleted) {
    if (RemoveLogin(form, nullptr)) {
      count_removed_logins++;
    }
  }

  if (count_removed_logins > 0) {
    UMA_HISTOGRAM_COUNTS_100("PasswordManager.RemovedCorruptedPasswords",
                             count_removed_logins);
  }

  if (count_removed_logins != forms_to_be_deleted.size()) {
    metrics_util::LogDeleteCorruptedPasswordsResult(
        metrics_util::DeleteCorruptedPasswordsResult::kItemFailure);
  } else if (count_removed_logins > 0) {
    DCHECK(password_recovery_util_);
    password_recovery_util_->RecordPasswordRecovery();
    metrics_util::LogDeleteCorruptedPasswordsResult(
        metrics_util::DeleteCorruptedPasswordsResult::kSuccessPasswordsDeleted);
  }
#endif

  if (!statement->Succeeded())
    return false;
  return true;
}

void LoginDatabase::InitializeStatementStrings(const SQLTableBuilder& builder) {
  // This method may be called multiple times, if Chrome switches backends and
  // LoginDatabase::DeleteAndRecreateDatabaseFile ends up being called. In those
  // case do not recompute the SQL statements, because they would end up the
  // same.
  if (!add_statement_.empty())
    return;

  // Initialize the cached strings.
  std::string all_column_names = builder.ListAllColumnNames();
  std::string right_amount_of_placeholders =
      GeneratePlaceholders(builder.NumberOfColumns());
  std::string all_unique_key_column_names = builder.ListAllUniqueKeyNames();
  std::string all_nonunique_key_column_names =
      builder.ListAllNonuniqueKeyNames();

  add_statement_ = "INSERT INTO logins (" + all_column_names + ") VALUES " +
                   right_amount_of_placeholders;
  DCHECK(add_replace_statement_.empty());
  add_replace_statement_ = "INSERT OR REPLACE INTO logins (" +
                           all_column_names + ") VALUES " +
                           right_amount_of_placeholders;
  DCHECK(update_statement_.empty());
  update_statement_ = "UPDATE OR REPLACE logins SET " +
                      all_nonunique_key_column_names + " WHERE " +
                      all_unique_key_column_names;
  DCHECK(delete_statement_.empty());
  delete_statement_ = "DELETE FROM logins WHERE " + all_unique_key_column_names;
  DCHECK(delete_by_id_statement_.empty());
  delete_by_id_statement_ = "DELETE FROM logins WHERE id=?";
  DCHECK(autosignin_statement_.empty());
  autosignin_statement_ = "SELECT " + all_column_names +
                          " FROM logins "
                          "WHERE skip_zero_click = 0 ORDER BY origin_url";
  DCHECK(get_statement_.empty());
  get_statement_ = "SELECT " + all_column_names +
                   " FROM logins "
                   "WHERE signon_realm == ?";
  std::string psl_statement = "OR signon_realm REGEXP ? ";
  std::string federated_statement =
      "OR (signon_realm LIKE ? AND password_type == 2) ";
  std::string psl_federated_statement =
      "OR (signon_realm REGEXP ? AND password_type == 2) ";
  DCHECK(get_statement_psl_.empty());
  get_statement_psl_ = get_statement_ + psl_statement;
  DCHECK(get_statement_federated_.empty());
  get_statement_federated_ = get_statement_ + federated_statement;
  DCHECK(get_statement_psl_federated_.empty());
  get_statement_psl_federated_ =
      get_statement_ + psl_statement + psl_federated_statement;
  DCHECK(get_same_organization_name_logins_statement_.empty());
  get_same_organization_name_logins_statement_ =
      "SELECT " + all_column_names +
      " FROM LOGINS"
      " WHERE scheme == 0 AND signon_realm REGEXP ?";
  DCHECK(created_statement_.empty());
  created_statement_ =
      "SELECT " + all_column_names +
      " FROM logins WHERE date_created >= ? AND date_created < "
      "? ORDER BY origin_url";
  DCHECK(synced_statement_.empty());
  synced_statement_ = "SELECT " + all_column_names +
                      " FROM logins WHERE date_synced >= ? AND date_synced < "
                      "? ORDER BY origin_url";
  DCHECK(blacklisted_statement_.empty());
  blacklisted_statement_ =
      "SELECT " + all_column_names +
      " FROM logins WHERE blacklisted_by_user == ? ORDER BY origin_url";
  DCHECK(encrypted_statement_.empty());
  encrypted_statement_ =
      "SELECT password_value FROM logins WHERE " + all_unique_key_column_names;
  DCHECK(encrypted_password_statement_by_id_.empty());
  encrypted_password_statement_by_id_ =
      "SELECT password_value FROM logins WHERE id=?";
  DCHECK(id_statement_.empty());
  id_statement_ = "SELECT id FROM logins WHERE " + all_unique_key_column_names;
}

bool LoginDatabase::IsUsingCleanupMechanism() const {
#if defined(OS_MACOSX) && !defined(OS_IOS)
  return base::FeatureList::IsEnabled(features::kDeleteCorruptedPasswords);
#else
  return false;
#endif
}

}  // namespace password_manager
