// Copyright (c) 2012 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 <stdarg.h>

#include "base/basictypes.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/password_manager/native_backend_gnome_x.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/autofill/core/common/password_form.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"

using autofill::PasswordForm;
using content::BrowserThread;

namespace {

// What follows is a very simple implementation of the subset of the GNOME
// Keyring API that we actually use. It gets substituted for the real one by
// MockGnomeKeyringLoader, which hooks into the facility normally used to load
// the GNOME Keyring library at runtime to avoid a static dependency on it.

struct MockKeyringItem {
  MockKeyringItem() {}
  MockKeyringItem(const char* keyring,
                  const std::string& display_name,
                  const std::string& password)
    : keyring(keyring ? keyring : "login"),
      display_name(display_name),
      password(password) {}

  struct ItemAttribute {
    ItemAttribute() : type(UINT32), value_uint32(0) {}
    explicit ItemAttribute(uint32_t value)
      : type(UINT32), value_uint32(value) {}
    explicit ItemAttribute(const std::string& value)
      : type(STRING), value_string(value) {}

    bool Equals(const ItemAttribute& x) const {
      if (type != x.type) return false;
      return (type == STRING) ? value_string == x.value_string
                              : value_uint32 == x.value_uint32;
    }

    enum Type { UINT32, STRING } type;
    uint32_t value_uint32;
    std::string value_string;
  };

  typedef std::map<std::string, ItemAttribute> attribute_map;
  typedef std::vector<std::pair<std::string, ItemAttribute> > attribute_query;

  bool Matches(const attribute_query& query) const {
    // The real GNOME Keyring doesn't match empty queries.
    if (query.empty()) return false;
    for (size_t i = 0; i < query.size(); ++i) {
      attribute_map::const_iterator match = attributes.find(query[i].first);
      if (match == attributes.end()) return false;
      if (!match->second.Equals(query[i].second)) return false;
    }
    return true;
  }

  std::string keyring;
  std::string display_name;
  std::string password;

  attribute_map attributes;
};

// The list of all keyring items we have stored.
std::vector<MockKeyringItem> mock_keyring_items;
bool mock_keyring_reject_local_ids = false;

bool IsStringAttribute(const GnomeKeyringPasswordSchema* schema,
                       const std::string& name) {
  for (size_t i = 0; schema->attributes[i].name; ++i)
    if (name == schema->attributes[i].name)
      return schema->attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
  NOTREACHED() << "Requested type of nonexistent attribute";
  return false;
}

gboolean mock_gnome_keyring_is_available() {
  return true;
}

gpointer mock_gnome_keyring_store_password(
    const GnomeKeyringPasswordSchema* schema,
    const gchar* keyring,
    const gchar* display_name,
    const gchar* password,
    GnomeKeyringOperationDoneCallback callback,
    gpointer data,
    GDestroyNotify destroy_data,
    ...) {
  mock_keyring_items.push_back(
      MockKeyringItem(keyring, display_name, password));
  MockKeyringItem* item = &mock_keyring_items.back();
  const std::string keyring_desc =
      keyring ? base::StringPrintf("keyring %s", keyring)
              : std::string("default keyring");
  VLOG(1) << "Adding item with origin " << display_name
          << " to " << keyring_desc;
  va_list ap;
  va_start(ap, destroy_data);
  char* name;
  while ((name = va_arg(ap, gchar*))) {
    if (IsStringAttribute(schema, name)) {
      item->attributes[name] =
          MockKeyringItem::ItemAttribute(va_arg(ap, gchar*));
      VLOG(1) << "Adding item attribute " << name
              << ", value '" << item->attributes[name].value_string << "'";
    } else {
      item->attributes[name] =
          MockKeyringItem::ItemAttribute(va_arg(ap, uint32_t));
      VLOG(1) << "Adding item attribute " << name
              << ", value " << item->attributes[name].value_uint32;
    }
  }
  va_end(ap);
  // As a hack to ease testing migration, make it possible to reject the new
  // format for the app string. This way we can add them easily to migrate.
  if (mock_keyring_reject_local_ids) {
    MockKeyringItem::attribute_map::iterator it =
        item->attributes.find("application");
    if (it != item->attributes.end() &&
        it->second.type == MockKeyringItem::ItemAttribute::STRING &&
        base::StringPiece(it->second.value_string).starts_with("chrome-")) {
      mock_keyring_items.pop_back();
      // GnomeKeyringResult, data
      callback(GNOME_KEYRING_RESULT_IO_ERROR, data);
      return NULL;
    }
  }
  // GnomeKeyringResult, data
  callback(GNOME_KEYRING_RESULT_OK, data);
  return NULL;
}

gpointer mock_gnome_keyring_delete_password(
    const GnomeKeyringPasswordSchema* schema,
    GnomeKeyringOperationDoneCallback callback,
    gpointer data,
    GDestroyNotify destroy_data,
    ...) {
  MockKeyringItem::attribute_query query;
  va_list ap;
  va_start(ap, destroy_data);
  char* name;
  while ((name = va_arg(ap, gchar*))) {
    if (IsStringAttribute(schema, name)) {
      query.push_back(make_pair(std::string(name),
          MockKeyringItem::ItemAttribute(va_arg(ap, gchar*))));
      VLOG(1) << "Querying with item attribute " << name
              << ", value '" << query.back().second.value_string << "'";
    } else {
      query.push_back(make_pair(std::string(name),
          MockKeyringItem::ItemAttribute(va_arg(ap, uint32_t))));
      VLOG(1) << "Querying with item attribute " << name
              << ", value " << query.back().second.value_uint32;
    }
  }
  va_end(ap);
  bool deleted = false;
  for (size_t i = mock_keyring_items.size(); i > 0; --i) {
    const MockKeyringItem* item = &mock_keyring_items[i - 1];
    if (item->Matches(query)) {
      VLOG(1) << "Deleting item with origin " <<  item->display_name;
      mock_keyring_items.erase(mock_keyring_items.begin() + (i - 1));
      deleted = true;
    }
  }
  // GnomeKeyringResult, data
  callback(deleted ? GNOME_KEYRING_RESULT_OK
                   : GNOME_KEYRING_RESULT_NO_MATCH, data);
  return NULL;
}

gpointer mock_gnome_keyring_find_itemsv(
    GnomeKeyringItemType type,
    GnomeKeyringOperationGetListCallback callback,
    gpointer data,
    GDestroyNotify destroy_data,
    ...) {
  MockKeyringItem::attribute_query query;
  va_list ap;
  va_start(ap, destroy_data);
  char* name;
  while ((name = va_arg(ap, gchar*))) {
    // Really a GnomeKeyringAttributeType, but promoted to int through ...
    if (va_arg(ap, int) == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) {
      query.push_back(make_pair(std::string(name),
          MockKeyringItem::ItemAttribute(va_arg(ap, gchar*))));
      VLOG(1) << "Querying with item attribute " << name
              << ", value '" << query.back().second.value_string << "'";
    } else {
      query.push_back(make_pair(std::string(name),
          MockKeyringItem::ItemAttribute(va_arg(ap, uint32_t))));
      VLOG(1) << "Querying with item attribute " << name
              << ", value " << query.back().second.value_uint32;
    }
  }
  va_end(ap);
  // Find matches and add them to a list of results.
  GList* results = NULL;
  for (size_t i = 0; i < mock_keyring_items.size(); ++i) {
    const MockKeyringItem* item = &mock_keyring_items[i];
    if (item->Matches(query)) {
      GnomeKeyringFound* found = new GnomeKeyringFound;
      found->keyring = strdup(item->keyring.c_str());
      found->item_id = i;
      found->attributes = gnome_keyring_attribute_list_new();
      for (MockKeyringItem::attribute_map::const_iterator it =
               item->attributes.begin();
           it != item->attributes.end();
           ++it) {
        if (it->second.type == MockKeyringItem::ItemAttribute::STRING) {
          gnome_keyring_attribute_list_append_string(
              found->attributes, it->first.c_str(),
              it->second.value_string.c_str());
        } else {
          gnome_keyring_attribute_list_append_uint32(
              found->attributes, it->first.c_str(),
              it->second.value_uint32);
        }
      }
      found->secret = strdup(item->password.c_str());
      results = g_list_prepend(results, found);
    }
  }
  // GnomeKeyringResult, GList*, data
  callback(results ? GNOME_KEYRING_RESULT_OK
                   : GNOME_KEYRING_RESULT_NO_MATCH, results, data);
  // Now free the list of results.
  GList* element = g_list_first(results);
  while (element) {
    GnomeKeyringFound* found = static_cast<GnomeKeyringFound*>(element->data);
    free(found->keyring);
    gnome_keyring_attribute_list_free(found->attributes);
    free(found->secret);
    delete found;
    element = g_list_next(element);
  }
  g_list_free(results);
  return NULL;
}

const gchar* mock_gnome_keyring_result_to_message(GnomeKeyringResult res) {
  return "mock keyring simulating failure";
}

// Inherit to get access to protected fields.
class MockGnomeKeyringLoader : public GnomeKeyringLoader {
 public:
  static bool LoadMockGnomeKeyring() {
#define GNOME_KEYRING_ASSIGN_POINTER(name) \
  gnome_keyring_##name = &mock_gnome_keyring_##name;
    GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_ASSIGN_POINTER)
#undef GNOME_KEYRING_ASSIGN_POINTER
    keyring_loaded = true;
    // Reset the state of the mock library.
    mock_keyring_items.clear();
    mock_keyring_reject_local_ids = false;
    return true;
  }
};

}  // anonymous namespace

class NativeBackendGnomeTest : public testing::Test {
 protected:
  NativeBackendGnomeTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        db_thread_(BrowserThread::DB) {
  }

  virtual void SetUp() {
    ASSERT_TRUE(db_thread_.Start());

    MockGnomeKeyringLoader::LoadMockGnomeKeyring();

    form_google_.origin = GURL("http://www.google.com/");
    form_google_.action = GURL("http://www.google.com/login");
    form_google_.username_element = UTF8ToUTF16("user");
    form_google_.username_value = UTF8ToUTF16("joeschmoe");
    form_google_.password_element = UTF8ToUTF16("pass");
    form_google_.password_value = UTF8ToUTF16("seekrit");
    form_google_.submit_element = UTF8ToUTF16("submit");
    form_google_.signon_realm = "Google";

    form_isc_.origin = GURL("http://www.isc.org/");
    form_isc_.action = GURL("http://www.isc.org/auth");
    form_isc_.username_element = UTF8ToUTF16("id");
    form_isc_.username_value = UTF8ToUTF16("janedoe");
    form_isc_.password_element = UTF8ToUTF16("passwd");
    form_isc_.password_value = UTF8ToUTF16("ihazabukkit");
    form_isc_.submit_element = UTF8ToUTF16("login");
    form_isc_.signon_realm = "ISC";
  }

  virtual void TearDown() {
    base::MessageLoop::current()->PostTask(FROM_HERE,
                                           base::MessageLoop::QuitClosure());
    base::MessageLoop::current()->Run();
    db_thread_.Stop();
  }

  void RunBothThreads() {
    // First we post a message to the DB thread that will run after all other
    // messages that have been posted to the DB thread (we don't expect more
    // to be posted), which posts a message to the UI thread to quit the loop.
    // That way we can run both loops and be sure that the UI thread loop will
    // quit so we can get on with the rest of the test.
    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
        base::Bind(&PostQuitTask, &message_loop_));
    base::MessageLoop::current()->Run();
  }

  static void PostQuitTask(base::MessageLoop* loop) {
    loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
  }

  void CheckUint32Attribute(const MockKeyringItem* item,
                            const std::string& attribute,
                            uint32_t value) {
    MockKeyringItem::attribute_map::const_iterator it =
        item->attributes.find(attribute);
    EXPECT_NE(item->attributes.end(), it);
    if (it != item->attributes.end()) {
      EXPECT_EQ(MockKeyringItem::ItemAttribute::UINT32, it->second.type);
      EXPECT_EQ(value, it->second.value_uint32);
    }
  }

  void CheckStringAttribute(const MockKeyringItem* item,
                            const std::string& attribute,
                            const std::string& value) {
    MockKeyringItem::attribute_map::const_iterator it =
        item->attributes.find(attribute);
    EXPECT_NE(item->attributes.end(), it);
    if (it != item->attributes.end()) {
      EXPECT_EQ(MockKeyringItem::ItemAttribute::STRING, it->second.type);
      EXPECT_EQ(value, it->second.value_string);
    }
  }

  void CheckMockKeyringItem(const MockKeyringItem* item,
                            const PasswordForm& form,
                            const std::string& app_string) {
    // We always add items to the login keyring.
    EXPECT_EQ("login", item->keyring);
    EXPECT_EQ(form.origin.spec(), item->display_name);
    EXPECT_EQ(UTF16ToUTF8(form.password_value), item->password);
    EXPECT_EQ(13u, item->attributes.size());
    CheckStringAttribute(item, "origin_url", form.origin.spec());
    CheckStringAttribute(item, "action_url", form.action.spec());
    CheckStringAttribute(item, "username_element",
                         UTF16ToUTF8(form.username_element));
    CheckStringAttribute(item, "username_value",
                         UTF16ToUTF8(form.username_value));
    CheckStringAttribute(item, "password_element",
                         UTF16ToUTF8(form.password_element));
    CheckStringAttribute(item, "submit_element",
                         UTF16ToUTF8(form.submit_element));
    CheckStringAttribute(item, "signon_realm", form.signon_realm);
    CheckUint32Attribute(item, "ssl_valid", form.ssl_valid);
    CheckUint32Attribute(item, "preferred", form.preferred);
    // We don't check the date created. It varies.
    CheckUint32Attribute(item, "blacklisted_by_user", form.blacklisted_by_user);
    CheckUint32Attribute(item, "scheme", form.scheme);
    CheckStringAttribute(item, "application", app_string);
  }

  base::MessageLoopForUI message_loop_;
  content::TestBrowserThread ui_thread_;
  content::TestBrowserThread db_thread_;

  TestingProfile profile_;

  // Provide some test forms to avoid having to set them up in each test.
  PasswordForm form_google_;
  PasswordForm form_isc_;
};

TEST_F(NativeBackendGnomeTest, BasicAddLogin) {
  // Pretend that the migration has already taken place.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  NativeBackendGnome backend(42, profile_.GetPrefs());
  backend.Init();

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));

  RunBothThreads();

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
}

TEST_F(NativeBackendGnomeTest, BasicListLogins) {
  // Pretend that the migration has already taken place.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  NativeBackendGnome backend(42, profile_.GetPrefs());
  backend.Init();

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult( &NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));

  std::vector<PasswordForm*> form_list;
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(
          base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
          base::Unretained(&backend), &form_list));

  RunBothThreads();

  // Quick check that we got something back.
  EXPECT_EQ(1u, form_list.size());
  STLDeleteElements(&form_list);

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
}

TEST_F(NativeBackendGnomeTest, BasicRemoveLogin) {
  // Pretend that the migration has already taken place.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  NativeBackendGnome backend(42, profile_.GetPrefs());
  backend.Init();

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));

  RunBothThreads();

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin),
                 base::Unretained(&backend), form_google_));

  RunBothThreads();

  EXPECT_EQ(0u, mock_keyring_items.size());
}

TEST_F(NativeBackendGnomeTest, RemoveNonexistentLogin) {
  // Pretend that the migration has already taken place.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  NativeBackendGnome backend(42, profile_.GetPrefs());
  backend.Init();

  // First add an unrelated login.
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));

  RunBothThreads();

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");

  // Attempt to remove a login that doesn't exist.
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin),
                 base::Unretained(&backend), form_isc_));

  // Make sure we can still get the first form back.
  std::vector<PasswordForm*> form_list;
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(
          base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
          base::Unretained(&backend), &form_list));

  RunBothThreads();

  // Quick check that we got something back.
  EXPECT_EQ(1u, form_list.size());
  STLDeleteElements(&form_list);

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
}

TEST_F(NativeBackendGnomeTest, AddDuplicateLogin) {
  // Pretend that the migration has already taken place.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  NativeBackendGnome backend(42, profile_.GetPrefs());
  backend.Init();

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));

  RunBothThreads();

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
}

TEST_F(NativeBackendGnomeTest, ListLoginsAppends) {
  // Pretend that the migration has already taken place.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  NativeBackendGnome backend(42, profile_.GetPrefs());
  backend.Init();

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                 base::Unretained(&backend), form_google_));

  // Send the same request twice with the same list both times.
  std::vector<PasswordForm*> form_list;
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(
          base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
          base::Unretained(&backend), &form_list));
  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
      base::Bind(
          base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
          base::Unretained(&backend), &form_list));

  RunBothThreads();

  // Quick check that we got two results back.
  EXPECT_EQ(2u, form_list.size());
  STLDeleteElements(&form_list);

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
}

// TODO(mdm): add more basic (i.e. non-migration) tests here at some point.

TEST_F(NativeBackendGnomeTest, DISABLED_MigrateOneLogin) {
  // Reject attempts to migrate so we can populate the store.
  mock_keyring_reject_local_ids = true;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                   base::Unretained(&backend), form_google_));

    // Make sure we can get the form back even when migration is failing.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got something back.
    EXPECT_EQ(1u, form_list.size());
    STLDeleteElements(&form_list);
  }

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");

  // Now allow the migration.
  mock_keyring_reject_local_ids = false;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    // This should not trigger migration because there will be no results.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::GetBlacklistLogins),
                   base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Check that we got nothing back.
    EXPECT_EQ(0u, form_list.size());
    STLDeleteElements(&form_list);
  }

  // Check that the keyring is unmodified.
  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");

  // Check that we haven't set the persistent preference.
  EXPECT_FALSE(
      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    // Trigger the migration by looking something up.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got something back.
    EXPECT_EQ(1u, form_list.size());
    STLDeleteElements(&form_list);
  }

  EXPECT_EQ(2u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
  if (mock_keyring_items.size() > 1)
    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");

  // Check that we have set the persistent preference.
  EXPECT_TRUE(
      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
}

TEST_F(NativeBackendGnomeTest, DISABLED_MigrateToMultipleProfiles) {
  // Reject attempts to migrate so we can populate the store.
  mock_keyring_reject_local_ids = true;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                   base::Unretained(&backend), form_google_));

    RunBothThreads();
  }

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");

  // Now allow the migration.
  mock_keyring_reject_local_ids = false;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    // Trigger the migration by looking something up.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got something back.
    EXPECT_EQ(1u, form_list.size());
    STLDeleteElements(&form_list);
  }

  EXPECT_EQ(2u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
  if (mock_keyring_items.size() > 1)
    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");

  // Check that we have set the persistent preference.
  EXPECT_TRUE(
      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));

  // Normally we'd actually have a different profile. But in the test just reset
  // the profile's persistent pref; we pass in the local profile id anyway.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);

  {
    NativeBackendGnome backend(24, profile_.GetPrefs());
    backend.Init();

    // Trigger the migration by looking something up.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got something back.
    EXPECT_EQ(1u, form_list.size());
    STLDeleteElements(&form_list);
  }

  EXPECT_EQ(3u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
  if (mock_keyring_items.size() > 1)
    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
  if (mock_keyring_items.size() > 2)
    CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24");
}

TEST_F(NativeBackendGnomeTest, DISABLED_NoMigrationWithPrefSet) {
  // Reject attempts to migrate so we can populate the store.
  mock_keyring_reject_local_ids = true;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                   base::Unretained(&backend), form_google_));

    RunBothThreads();
  }

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");

  // Now allow migration, but also pretend that the it has already taken place.
  mock_keyring_reject_local_ids = false;
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    // Trigger the migration by adding a new login.
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                   base::Unretained(&backend), form_isc_));

    // Look up all logins; we expect only the one we added.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got the right thing back.
    EXPECT_EQ(1u, form_list.size());
    if (form_list.size() > 0)
      EXPECT_EQ(form_isc_.signon_realm, form_list[0]->signon_realm);
    STLDeleteElements(&form_list);
  }

  EXPECT_EQ(2u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
  if (mock_keyring_items.size() > 1)
    CheckMockKeyringItem(&mock_keyring_items[1], form_isc_, "chrome-42");
}

TEST_F(NativeBackendGnomeTest, DISABLED_DeleteMigratedPasswordIsIsolated) {
  // Reject attempts to migrate so we can populate the store.
  mock_keyring_reject_local_ids = true;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                   base::Unretained(&backend), form_google_));

    RunBothThreads();
  }

  EXPECT_EQ(1u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");

  // Now allow the migration.
  mock_keyring_reject_local_ids = false;

  {
    NativeBackendGnome backend(42, profile_.GetPrefs());
    backend.Init();

    // Trigger the migration by looking something up.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got something back.
    EXPECT_EQ(1u, form_list.size());
    STLDeleteElements(&form_list);
  }

  EXPECT_EQ(2u, mock_keyring_items.size());
  if (mock_keyring_items.size() > 0)
    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
  if (mock_keyring_items.size() > 1)
    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");

  // Check that we have set the persistent preference.
  EXPECT_TRUE(
      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));

  // Normally we'd actually have a different profile. But in the test just reset
  // the profile's persistent pref; we pass in the local profile id anyway.
  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);

  {
    NativeBackendGnome backend(24, profile_.GetPrefs());
    backend.Init();

    // Trigger the migration by looking something up.
    std::vector<PasswordForm*> form_list;
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(
            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
            base::Unretained(&backend), &form_list));

    RunBothThreads();

    // Quick check that we got something back.
    EXPECT_EQ(1u, form_list.size());
    STLDeleteElements(&form_list);

    // There should be three passwords now.
    EXPECT_EQ(3u, mock_keyring_items.size());
    if (mock_keyring_items.size() > 0)
      CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
    if (mock_keyring_items.size() > 1)
      CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
    if (mock_keyring_items.size() > 2)
      CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24");

    // Now delete the password from this second profile.
    BrowserThread::PostTask(
        BrowserThread::DB, FROM_HERE,
        base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin),
                   base::Unretained(&backend), form_google_));

    RunBothThreads();

    // The other two copies of the password in different profiles should remain.
    EXPECT_EQ(2u, mock_keyring_items.size());
    if (mock_keyring_items.size() > 0)
      CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
    if (mock_keyring_items.size() > 1)
      CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
  }
}
