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 "chrome/browser/password_manager/password_store_x.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/password_manager/core/browser/password_store_change.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/password_manager/core/common/password_manager_pref_names.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordForm;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing password_manager::PasswordStoreChange;
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing password_manager::PasswordStoreChangeList;
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing password_manager::PasswordStoreDefault;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool AddLoginToBackend(const scoped_ptr<PasswordStoreX::NativeBackend>& backend,
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       const PasswordForm& form,
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       PasswordStoreChangeList* changes) {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *changes = backend->AddLogin(form);
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (!changes->empty() &&
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          changes->back().type() == PasswordStoreChange::ADD);
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreX::PasswordStoreX(
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner,
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    password_manager::LoginDatabase* login_db,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NativeBackend* backend)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : PasswordStoreDefault(main_thread_runner, db_thread_runner, login_db),
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      backend_(backend),
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      migration_checked_(!backend),
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      allow_fallback_(false) {}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordStoreX::~PasswordStoreX() {}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::AddLoginImpl(const PasswordForm& form) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (use_native_backend() && AddLoginToBackend(backend_, form, &changes)) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::AddLoginImpl(form);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::UpdateLoginImpl(
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PasswordForm& form) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (use_native_backend() && backend_->UpdateLogin(form, &changes)) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::UpdateLoginImpl(form);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::RemoveLoginImpl(
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PasswordForm& form) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->RemoveLogin(form)) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::RemoveLoginImpl(form);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::RemoveLoginsCreatedBetweenImpl(
906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::Time delete_begin,
916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::Time delete_end) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() &&
956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      backend_->RemoveLoginsCreatedBetween(
966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          delete_begin, delete_end, &changes)) {
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LogStatsForBulkDeletion(changes.size());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(delete_begin,
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                                   delete_end);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::RemoveLoginsSyncedBetweenImpl(
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::Time delete_begin,
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::Time delete_end) {
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CheckMigration();
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PasswordStoreChangeList changes;
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (use_native_backend() &&
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      backend_->RemoveLoginsSyncedBetween(delete_begin, delete_end, &changes)) {
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    allow_fallback_ = false;
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (allow_default_store()) {
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    changes = PasswordStoreDefault::RemoveLoginsSyncedBetweenImpl(delete_begin,
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                                  delete_end);
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return changes;
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LoginLessThan {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const PasswordForm* a, const PasswordForm* b) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->origin < b->origin;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::SortLoginsByOrigin(NativeBackend::PasswordFormList* list) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In login_database.cc, the query has ORDER BY origin_url. Simulate that.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(list->begin(), list->end(), LoginLessThan());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordStoreX::GetLoginsImpl(
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const autofill::PasswordForm& form,
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AuthorizationPromptPolicy prompt_policy,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConsumerCallbackRunner& callback_runner) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::vector<autofill::PasswordForm*> matched_forms;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (use_native_backend() && backend_->GetLogins(form, &matched_forms)) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SortLoginsByOrigin(&matched_forms);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The native backend may succeed and return no data even while locked, if
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the query did not match anything stored. So we continue to allow fallback
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // until we perform a write operation, or until a read returns actual data.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (matched_forms.size() > 0)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(matched_forms.empty());
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStoreDefault::GetLoginsImpl(form, prompt_policy, callback_runner);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The consumer will be left hanging unless we reply.
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback_runner.Run(matched_forms);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::GetAutofillableLoginsImpl(GetLoginsRequest* request) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() &&
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      backend_->GetAutofillableLogins(request->result())) {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SortLoginsByOrigin(request->result());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->result()->size() > 0)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreDefault::GetAutofillableLoginsImpl(request);
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The consumer will be left hanging unless we reply.
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ForwardLoginsResult(request);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() &&
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      backend_->GetBlacklistLogins(request->result())) {
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SortLoginsByOrigin(request->result());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->result()->size() > 0)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreDefault::GetBlacklistLoginsImpl(request);
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The consumer will be left hanging unless we reply.
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ForwardLoginsResult(request);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::FillAutofillableLogins(vector<PasswordForm*>* forms) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->GetAutofillableLogins(forms)) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (forms->size() > 0)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_default_store())
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PasswordStoreDefault::FillAutofillableLogins(forms);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::FillBlacklistLogins(vector<PasswordForm*>* forms) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->GetBlacklistLogins(forms)) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (forms->size() > 0)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_default_store())
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PasswordStoreDefault::FillBlacklistLogins(forms);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::CheckMigration() {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (migration_checked_ || !backend_.get())
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  migration_checked_ = true;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t migrated = MigrateLogins();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (migrated > 0) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Migrated " << migrated << " passwords to native store.";
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (migrated == 0) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // As long as we are able to migrate some passwords, we know the native
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // store is working. But if there is nothing to migrate, the "migration"
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can succeed even when the native store would fail. In this case we
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // allow a later fallback to the default store. Once any later operation
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // succeeds on the native store, we will no longer allow fallback.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = true;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Native password store migration failed! " <<
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "Falling back on default (unencrypted) store.";
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_.reset(NULL);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::allow_default_store() {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_fallback_) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Native password store failed! " <<
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "Falling back on default (unencrypted) store.";
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_.reset(NULL);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't warn again. We'll use the default store because backend_ is NULL.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !backend_.get();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t PasswordStoreX::MigrateLogins() {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backend_.get());
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<PasswordForm*> forms;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = PasswordStoreDefault::FillAutofillableLogins(&forms) &&
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PasswordStoreDefault::FillBlacklistLogins(&forms);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We add all the passwords (and blacklist entries) to the native backend
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before attempting to remove any from the login database, to make sure we
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // don't somehow end up with some of the passwords in one store and some in
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // another. We'll always have at least one intact store this way.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < forms.size(); ++i) {
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      PasswordStoreChangeList changes;
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!AddLoginToBackend(backend_, *forms[i], &changes)) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ok = false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < forms.size(); ++i) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If even one of these calls to RemoveLoginImpl() succeeds, then we
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // should prefer the native backend to the now-incomplete login
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // database. Thus we want to return a success status even in the case
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // where some fail. The only real problem with this is that we might
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // leave passwords in the login database and never come back to clean
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // them out if any of these calls do fail.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PasswordStoreDefault::RemoveLoginImpl(*forms[i]);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Finally, delete the database file itself. We remove the passwords from
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // it before deleting the file just in case there is some problem deleting
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the file (e.g. directory is not writable, but file is), which would
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // otherwise cause passwords to re-migrate next (or maybe every) time.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeleteAndRecreateDatabaseFile();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t result = ok ? forms.size() : -1;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&forms);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285