password_store_x.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/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;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreX::PasswordStoreX(
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner,
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LoginDatabase* login_db,
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NativeBackend* backend)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : PasswordStoreDefault(main_thread_runner, db_thread_runner, login_db),
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      backend_(backend),
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      migration_checked_(!backend),
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      allow_fallback_(false) {}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordStoreX::~PasswordStoreX() {}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::AddLoginImpl(const PasswordForm& form) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->AddLogin(form)) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::AddLoginImpl(form);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::UpdateLoginImpl(
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PasswordForm& form) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->UpdateLogin(form)) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::UpdateLoginImpl(form);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::RemoveLoginImpl(
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PasswordForm& form) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->RemoveLogin(form)) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::RemoveLoginImpl(form);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStoreChangeList PasswordStoreX::RemoveLoginsCreatedBetweenImpl(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& delete_begin,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& delete_end) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<PasswordForm*> forms;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() &&
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_->GetLoginsCreatedBetween(delete_begin, delete_end, &forms) &&
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_->RemoveLoginsCreatedBetween(delete_begin, delete_end)) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (vector<PasswordForm*>::const_iterator it = forms.begin();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != forms.end(); ++it) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            **it));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LogStatsForBulkDeletion(changes.size());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    changes = PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(delete_begin,
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                                   delete_end);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&forms);
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return changes;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LoginLessThan {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const PasswordForm* a, const PasswordForm* b) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->origin < b->origin;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::SortLoginsByOrigin(NativeBackend::PasswordFormList* list) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In login_database.cc, the query has ORDER BY origin_url. Simulate that.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(list->begin(), list->end(), LoginLessThan());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordStoreX::GetLoginsImpl(
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const autofill::PasswordForm& form,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AuthorizationPromptPolicy prompt_policy,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConsumerCallbackRunner& callback_runner) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::vector<autofill::PasswordForm*> matched_forms;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (use_native_backend() && backend_->GetLogins(form, &matched_forms)) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SortLoginsByOrigin(&matched_forms);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The native backend may succeed and return no data even while locked, if
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the query did not match anything stored. So we continue to allow fallback
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // until we perform a write operation, or until a read returns actual data.
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (matched_forms.size() > 0)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(matched_forms.empty());
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStoreDefault::GetLoginsImpl(form, prompt_policy, callback_runner);
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The consumer will be left hanging unless we reply.
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback_runner.Run(matched_forms);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::GetAutofillableLoginsImpl(GetLoginsRequest* request) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() &&
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      backend_->GetAutofillableLogins(request->result())) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SortLoginsByOrigin(request->result());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->result()->size() > 0)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreDefault::GetAutofillableLoginsImpl(request);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The consumer will be left hanging unless we reply.
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ForwardLoginsResult(request);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() &&
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      backend_->GetBlacklistLogins(request->result())) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SortLoginsByOrigin(request->result());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->result()->size() > 0)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (allow_default_store()) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStoreDefault::GetBlacklistLoginsImpl(request);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The consumer will be left hanging unless we reply.
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ForwardLoginsResult(request);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::FillAutofillableLogins(vector<PasswordForm*>* forms) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->GetAutofillableLogins(forms)) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (forms->size() > 0)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_default_store())
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PasswordStoreDefault::FillAutofillableLogins(forms);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::FillBlacklistLogins(vector<PasswordForm*>* forms) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckMigration();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_native_backend() && backend_->GetBlacklistLogins(forms)) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See GetLoginsImpl() for why we disallow fallback conditionally here.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (forms->size() > 0)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allow_fallback_ = false;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_default_store())
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PasswordStoreDefault::FillBlacklistLogins(forms);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::CheckMigration() {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (migration_checked_ || !backend_.get())
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  migration_checked_ = true;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t migrated = MigrateLogins();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (migrated > 0) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Migrated " << migrated << " passwords to native store.";
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (migrated == 0) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // As long as we are able to migrate some passwords, we know the native
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // store is working. But if there is nothing to migrate, the "migration"
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can succeed even when the native store would fail. In this case we
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // allow a later fallback to the default store. Once any later operation
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // succeeds on the native store, we will no longer allow fallback.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Native password store migration failed! " <<
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "Falling back on default (unencrypted) store.";
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_.reset(NULL);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::allow_default_store() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_fallback_) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Native password store failed! " <<
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "Falling back on default (unencrypted) store.";
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_.reset(NULL);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't warn again. We'll use the default store because backend_ is NULL.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_fallback_ = false;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !backend_.get();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t PasswordStoreX::MigrateLogins() {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backend_.get());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<PasswordForm*> forms;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = PasswordStoreDefault::FillAutofillableLogins(&forms) &&
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PasswordStoreDefault::FillBlacklistLogins(&forms);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We add all the passwords (and blacklist entries) to the native backend
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before attempting to remove any from the login database, to make sure we
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // don't somehow end up with some of the passwords in one store and some in
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // another. We'll always have at least one intact store this way.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < forms.size(); ++i) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!backend_->AddLogin(*forms[i])) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ok = false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < forms.size(); ++i) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If even one of these calls to RemoveLoginImpl() succeeds, then we
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // should prefer the native backend to the now-incomplete login
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // database. Thus we want to return a success status even in the case
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // where some fail. The only real problem with this is that we might
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // leave passwords in the login database and never come back to clean
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // them out if any of these calls do fail.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PasswordStoreDefault::RemoveLoginImpl(*forms[i]);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Finally, delete the database file itself. We remove the passwords from
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // it before deleting the file just in case there is some problem deleting
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the file (e.g. directory is not writable, but file is), which would
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // otherwise cause passwords to re-migrate next (or maybe every) time.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeleteAndRecreateDatabaseFile();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t result = ok ? forms.size() : -1;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&forms);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PasswordStoreX::RegisterProfilePrefs(
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Normally we should be on the UI thread here, but in tests we might not.
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterBooleanPref(
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kPasswordsUseLocalProfileId,
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // default: passwords don't use local ids
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      false,
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordStoreX::PasswordsUseLocalProfileId(PrefService* prefs) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Normally we should be on the UI thread here, but in tests we might not.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prefs->GetBoolean(prefs::kPasswordsUseLocalProfileId);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is a hack to do something not entirely thread safe: the pref
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// service comes from the UI thread, but it's not ref counted. We keep a pointer
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to it on the DB thread, and need to invoke a method on the UI thread. This
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function does that for us without requiring ref counting the pref service.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(mdm): Fix this if it becomes a problem. Given that this function will
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be called once ever per profile, it probably will not cause a problem...
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UISetPasswordsUseLocalProfileId(PrefService* prefs) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreX::SetPasswordsUseLocalProfileId(PrefService* prefs) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method should work on any thread, but we expect the DB thread.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&UISetPasswordsUseLocalProfileId, prefs));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
302