password_store_x_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/scoped_temp_dir.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_form_data.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store_change.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store_consumer.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store_x.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/pref_service.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_browser_process.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/mock_notification_observer.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::WaitableEvent;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::DoAll;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::ElementsAreArray;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Pointee;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Property;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::WithArg;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PasswordForm;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::vector<PasswordForm*> VectorOfForms;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockPasswordStoreConsumer : public PasswordStoreConsumer {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD2(OnPasswordStoreRequestDone,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               void(CancelableRequestProvider::Handle,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::vector<PasswordForm*>&));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class will add and remove a mock notification observer from
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the DB thread.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DBThreadObserverHelper
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<DBThreadObserverHelper,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        BrowserThread::DeleteOnDBThread> {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBThreadObserverHelper() : done_event_(true, false) {}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init(PasswordStore* password_store) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::DB,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&DBThreadObserverHelper::AddObserverTask,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   this, make_scoped_refptr(password_store)));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done_event_.Wait();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MockNotificationObserver& observer() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observer_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::DeleteHelper<DBThreadObserverHelper>;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DBThreadObserverHelper() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.RemoveAll();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddObserverTask(PasswordStore* password_store) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(&observer_,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   chrome::NOTIFICATION_LOGINS_CHANGED,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   content::Source<PasswordStore>(password_store));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done_event_.Signal();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent done_event_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MockNotificationObserver observer_;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FailingBackend : public PasswordStoreX::NativeBackend {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Init() { return true; }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool AddLogin(const PasswordForm& form) { return false; }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool UpdateLogin(const PasswordForm& form) { return false; }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RemoveLogin(const PasswordForm& form) { return false; }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RemoveLoginsCreatedBetween(const base::Time& delete_begin,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const base::Time& delete_end) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetLogins(const PasswordForm& form, PasswordFormList* forms) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetLoginsCreatedBetween(const base::Time& get_begin,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const base::Time& get_end,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       PasswordFormList* forms) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetAutofillableLogins(PasswordFormList* forms) { return false; }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetBlacklistLogins(PasswordFormList* forms) { return false; }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockBackend : public PasswordStoreX::NativeBackend {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Init() { return true; }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool AddLogin(const PasswordForm& form) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    all_forms_.push_back(form);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool UpdateLogin(const PasswordForm& form) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (CompareForms(all_forms_[i], form, true))
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all_forms_[i] = form;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RemoveLogin(const PasswordForm& form) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (CompareForms(all_forms_[i], form, false))
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        erase(i--);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RemoveLoginsCreatedBetween(const base::Time& delete_begin,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const base::Time& delete_end) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (delete_begin <= all_forms_[i].date_created &&
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (delete_end.is_null() || all_forms_[i].date_created < delete_end))
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        erase(i--);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetLogins(const PasswordForm& form, PasswordFormList* forms) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (all_forms_[i].signon_realm == form.signon_realm)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        forms->push_back(new PasswordForm(all_forms_[i]));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetLoginsCreatedBetween(const base::Time& get_begin,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const base::Time& get_end,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       PasswordFormList* forms) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (get_begin <= all_forms_[i].date_created &&
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (get_end.is_null() || all_forms_[i].date_created < get_end))
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        forms->push_back(new PasswordForm(all_forms_[i]));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetAutofillableLogins(PasswordFormList* forms) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!all_forms_[i].blacklisted_by_user)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        forms->push_back(new PasswordForm(all_forms_[i]));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetBlacklistLogins(PasswordFormList* forms) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < all_forms_.size(); ++i)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (all_forms_[i].blacklisted_by_user)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        forms->push_back(new PasswordForm(all_forms_[i]));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void erase(size_t index) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index < all_forms_.size() - 1)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      all_forms_[index] = all_forms_[all_forms_.size() - 1];
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    all_forms_.pop_back();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CompareForms(const PasswordForm& a, const PasswordForm& b, bool update) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // An update check doesn't care about the submit element.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!update && a.submit_element != b.submit_element)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a.origin           == b.origin &&
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           a.password_element == b.password_element &&
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           a.signon_realm     == b.signon_realm &&
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           a.username_element == b.username_element &&
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           a.username_value   == b.username_value;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PasswordForm> all_forms_;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockLoginDatabaseReturn {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(OnLoginDatabaseQueryDone,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               void(const std::vector<PasswordForm*>&));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LoginDatabaseQueryCallback(LoginDatabase* login_db,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool autofillable,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                MockLoginDatabaseReturn* mock_return) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PasswordForm*> forms;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (autofillable)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_db->GetAutofillableLogins(&forms);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_db->GetBlacklistLogins(&forms);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_return->OnLoginDatabaseQueryDone(forms);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate |count| expected logins, either auto-fillable or blacklisted.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitExpectedForms(bool autofillable, size_t count, VectorOfForms* forms) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* domain = autofillable ? "example" : "blacklisted";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < count; ++i) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string realm = base::StringPrintf("http://%zu.%s.com", i, domain);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string origin = base::StringPrintf("http://%zu.%s.com/origin",
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            i, domain);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string action = base::StringPrintf("http://%zu.%s.com/action",
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            i, domain);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordFormData data = {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PasswordForm::SCHEME_HTML,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      realm.c_str(),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin.c_str(),
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      action.c_str(),
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"submit_element",
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"username_element",
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"password_element",
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      autofillable ? L"username_value" : NULL,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      autofillable ? L"password_value" : NULL,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      autofillable, false, i + 1 };
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    forms->push_back(CreatePasswordFormFromData(data));
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum BackendType {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NO_BACKEND,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FAILING_BACKEND,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WORKING_BACKEND
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PasswordStoreXTest : public testing::TestWithParam<BackendType> {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordStoreXTest()
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_thread_(BrowserThread::UI, &message_loop_),
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        db_thread_(BrowserThread::DB) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(db_thread_.Start());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_.reset(new TestingProfile());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_db_.reset(new LoginDatabase());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append("login_test")));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->Run();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_thread_.Stop();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordStoreX::NativeBackend* GetBackend() {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (GetParam()) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FAILING_BACKEND:
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return new FailingBackend();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case WORKING_BACKEND:
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return new MockBackend();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoopForUI message_loop_;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PasswordStore, WDS schedule work on this thread.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread db_thread_;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LoginDatabase> login_db_;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedTempDir temp_dir_;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION(STLDeleteElements0) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(arg0.begin(), arg0.end());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION(QuitUIMessageLoop) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->Quit();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(PasswordStoreXTest, Notifications) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PasswordStoreX> store(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PasswordStoreX(login_db_.release(),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         profile_.get(),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetBackend()));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->Init();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordFormData form_data =
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { PasswordForm::SCHEME_HTML,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://bar.example.com",
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://bar.example.com/origin",
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://bar.example.com/action",
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    L"submit_element",
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    L"username_element",
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    L"password_element",
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    L"username_value",
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    L"password_value",
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    true, false, 1 };
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<DBThreadObserverHelper> helper = new DBThreadObserverHelper;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper->Init(store);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PasswordStoreChange expected_add_changes[] = {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreChange(PasswordStoreChange::ADD, *form),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(helper->observer(),
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED),
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              content::Source<PasswordStore>(store),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Property(&content::Details<const PasswordStoreChangeList>::ptr,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       Pointee(ElementsAreArray(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           expected_add_changes)))));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adding a login should trigger a notification.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->AddLogin(*form);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The PasswordStore schedules tasks to run on the DB thread so we schedule
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // yet another task to notify us that it's safe to carry on with the test.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent done(false, false);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Wait();
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change the password.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  form->password_value = WideToUTF16(L"a different password");
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PasswordStoreChange expected_update_changes[] = {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreChange(PasswordStoreChange::UPDATE, *form),
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(helper->observer(),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              content::Source<PasswordStore>(store),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Property(&content::Details<const PasswordStoreChangeList>::ptr,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       Pointee(ElementsAreArray(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           expected_update_changes)))));
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updating the login with the new password should trigger a notification.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->UpdateLogin(*form);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for PasswordStore to send the notification.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Wait();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PasswordStoreChange expected_delete_changes[] = {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreChange(PasswordStoreChange::REMOVE, *form),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(helper->observer(),
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              content::Source<PasswordStore>(store),
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Property(&content::Details<const PasswordStoreChangeList>::ptr,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       Pointee(ElementsAreArray(
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           expected_delete_changes)))));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deleting the login should trigger a notification.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->RemoveLogin(*form);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for PasswordStore to send the notification.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Wait();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Public in PasswordStore, protected in PasswordStoreX.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<PasswordStore*>(store)->ShutdownOnUIThread();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(PasswordStoreXTest, NativeMigration) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VectorOfForms expected_autofillable;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitExpectedForms(true, 50, &expected_autofillable);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VectorOfForms expected_blacklisted;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitExpectedForms(false, 50, &expected_blacklisted);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the initial size of the login DB file, before we populate it.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will be used later to make sure it gets back to this size.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FilePath login_db_file = temp_dir_.path().Append("login_test");
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformFileInfo db_file_start_info;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_start_info));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoginDatabase* login_db = login_db_.get();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populate the login DB with logins that should be migrated.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (VectorOfForms::iterator it = expected_autofillable.begin();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != expected_autofillable.end(); ++it) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::Bind(
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::IgnoreResult(&LoginDatabase::AddLogin),
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::Unretained(login_db), **it));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (VectorOfForms::iterator it = expected_blacklisted.begin();
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != expected_blacklisted.end(); ++it) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::Bind(
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::IgnoreResult(&LoginDatabase::AddLogin),
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::Unretained(login_db), **it));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule another task on the DB thread to notify us that it's safe to
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // carry on with the test.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent done(false, false);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Wait();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the new size of the login DB file. We expect it to be larger.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformFileInfo db_file_full_info;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_full_info));
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(db_file_full_info.size, db_file_start_info.size);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializing the PasswordStore shouldn't trigger a native migration (yet).
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PasswordStoreX> store(
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PasswordStoreX(login_db_.release(),
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         profile_.get(),
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetBackend()));
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->Init();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockPasswordStoreConsumer consumer;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we quit the MessageLoop even if the test fails.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ON_CALL(consumer, OnPasswordStoreRequestDone(_, _))
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillByDefault(QuitUIMessageLoop());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The autofillable forms should have been migrated to the native backend.
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(consumer,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnPasswordStoreRequestDone(_,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContainsAllPasswordForms(expected_autofillable)))
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop()));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->GetAutofillableLogins(&consumer);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->Run();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The blacklisted forms should have been migrated to the native backend.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(consumer,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnPasswordStoreRequestDone(_,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ContainsAllPasswordForms(expected_blacklisted)))
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop()));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store->GetBlacklistLogins(&consumer);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->Run();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VectorOfForms empty;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockLoginDatabaseReturn ld_return;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetParam() == WORKING_BACKEND) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No autofillable logins should be left in the login DB.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(ld_return,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty)));
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The autofillable logins should still be in the login DB.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(ld_return,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                OnLoginDatabaseQueryDone(
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ContainsAllPasswordForms(expected_autofillable)))
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .WillOnce(WithArg<0>(STLDeleteElements0()));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::DB, FROM_HERE,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&LoginDatabaseQueryCallback, login_db, true, &ld_return));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the login DB methods to execute on the DB thread.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Wait();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetParam() == WORKING_BACKEND) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Likewise, no blacklisted logins should be left in the login DB.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(ld_return,
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty)));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The blacklisted logins should still be in the login DB.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(ld_return,
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                OnLoginDatabaseQueryDone(
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ContainsAllPasswordForms(expected_blacklisted)))
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .WillOnce(WithArg<0>(STLDeleteElements0()));
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::DB, FROM_HERE,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&LoginDatabaseQueryCallback, login_db, false, &ld_return));
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the login DB methods to execute on the DB thread.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&WaitableEvent::Signal, base::Unretained(&done)));
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Wait();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetParam() == WORKING_BACKEND) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the migration succeeded, then not only should there be no logins left
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the login DB, but also the file should have been deleted and then
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // recreated. We approximate checking for this by checking that the file
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // size is equal to the size before we populated it, even though it was
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // larger after populating it.
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::PlatformFileInfo db_file_end_info;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_end_info));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(db_file_start_info.size, db_file_end_info.size);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&expected_autofillable);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&expected_blacklisted);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Public in PasswordStore, protected in PasswordStoreX.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<PasswordStore*>(store)->ShutdownOnUIThread();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(NoBackend,
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PasswordStoreXTest,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        testing::Values(NO_BACKEND));
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(FailingBackend,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PasswordStoreXTest,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        testing::Values(FAILING_BACKEND));
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(WorkingBackend,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PasswordStoreXTest,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        testing::Values(WORKING_BACKEND));
548