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