15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/password_manager/core/browser/password_store.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/debug/dump_without_crashing.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/autofill/core/common/password_form.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/password_manager/core/browser/password_store_consumer.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/password_manager/core/browser/password_syncable_service.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/password_manager/core/browser/password_syncable_service.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using autofill::PasswordForm;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace password_manager {
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Calls |consumer| back with the request result, if |consumer| is still alive.
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Takes ownership of the elements in |result|, passing ownership to |consumer|
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// if it is still alive.
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MaybeCallConsumerCallback(base::WeakPtr<PasswordStoreConsumer> consumer,
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               scoped_ptr<std::vector<PasswordForm*> > result) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (consumer.get())
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    consumer->OnGetPasswordStoreResults(*result);
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STLDeleteElements(result.get());
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// http://crbug.com/404012. Let's see where the empty fields come from.
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckForEmptyUsernameAndPassword(const PasswordForm& form) {
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (form.username_value.empty() &&
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      form.password_value.empty() &&
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !form.blacklisted_by_user)
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::debug::DumpWithoutCrashing();
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStore::GetLoginsRequest::GetLoginsRequest(
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStoreConsumer* consumer)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : consumer_weak_(consumer->GetWeakPtr()),
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      result_(new std::vector<PasswordForm*>()) {
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  origin_loop_ = base::MessageLoopProxy::current();
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStore::GetLoginsRequest::~GetLoginsRequest() {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::GetLoginsRequest::ApplyIgnoreLoginsCutoff() {
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ignore_logins_cutoff_.is_null()) {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Count down rather than up since we may be deleting elements.
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note that in principle it could be more efficient to copy the whole array
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // since that's worst-case linear time, but we expect that elements will be
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // deleted rarely and lists will be small, so this avoids the copies.
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (size_t i = result_->size(); i > 0; --i) {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if ((*result_)[i - 1]->date_created < ignore_logins_cutoff_) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delete (*result_)[i - 1];
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        result_->erase(result_->begin() + (i - 1));
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::GetLoginsRequest::ForwardResult() {
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  origin_loop_->PostTask(FROM_HERE,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         base::Bind(&MaybeCallConsumerCallback,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    consumer_weak_,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    base::Passed(result_.Pass())));
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStore::PasswordStore(
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : main_thread_runner_(main_thread_runner),
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      db_thread_runner_(db_thread_runner),
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      observers_(new ObserverListThreadSafe<Observer>()),
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      shutdown_called_(false) {}
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool PasswordStore::Init(const syncer::SyncableService::StartSyncFlare& flare,
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         const std::string& sync_username) {
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ReportMetrics(sync_username);
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScheduleTask(base::Bind(&PasswordStore::InitSyncableService, this, flare));
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::AddLogin(const PasswordForm& form) {
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CheckForEmptyUsernameAndPassword(form);
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScheduleTask(
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&PasswordStore::WrapModificationTask, this,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Bind(&PasswordStore::AddLoginImpl, this, form)));
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::UpdateLogin(const PasswordForm& form) {
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CheckForEmptyUsernameAndPassword(form);
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScheduleTask(
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&PasswordStore::WrapModificationTask, this,
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Bind(&PasswordStore::UpdateLoginImpl, this, form)));
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::RemoveLogin(const PasswordForm& form) {
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScheduleTask(
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&PasswordStore::WrapModificationTask, this,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Bind(&PasswordStore::RemoveLoginImpl, this, form)));
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void PasswordStore::RemoveLoginsCreatedBetween(base::Time delete_begin,
1206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                               base::Time delete_end) {
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScheduleTask(
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&PasswordStore::WrapModificationTask, this,
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Bind(&PasswordStore::RemoveLoginsCreatedBetweenImpl,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            this, delete_begin, delete_end)));
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void PasswordStore::RemoveLoginsSyncedBetween(base::Time delete_begin,
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              base::Time delete_end) {
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScheduleTask(
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&PasswordStore::WrapModificationTask,
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 this,
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 base::Bind(&PasswordStore::RemoveLoginsSyncedBetweenImpl,
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            this,
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            delete_begin,
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            delete_end)));
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::GetLogins(
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PasswordForm& form,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AuthorizationPromptPolicy prompt_policy,
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStoreConsumer* consumer) {
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Per http://crbug.com/121738, we deliberately ignore saved logins for
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // http*://www.google.com/ that were stored prior to 2012. (Google now uses
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // https://accounts.google.com/ for all login forms, so these should be
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // unused.) We don't delete them just yet, and they'll still be visible in the
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // password manager, but we won't use them to autofill any forms. This is a
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // security feature to help minimize damage that can be done by XSS attacks.
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(mdm): actually delete them at some point, say M24 or so.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Time ignore_logins_cutoff;  // the null time
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (form.scheme == PasswordForm::SCHEME_HTML &&
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (form.signon_realm == "http://www.google.com" ||
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       form.signon_realm == "http://www.google.com/" ||
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       form.signon_realm == "https://www.google.com" ||
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       form.signon_realm == "https://www.google.com/")) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    static const base::Time::Exploded exploded_cutoff =
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        { 2012, 1, 0, 1, 0, 0, 0, 0 };  // 00:00 Jan 1 2012
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ignore_logins_cutoff = base::Time::FromUTCExploded(exploded_cutoff);
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetLoginsRequest* request = new GetLoginsRequest(consumer);
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->set_ignore_logins_cutoff(ignore_logins_cutoff);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConsumerCallbackRunner callback_runner =
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&PasswordStore::CopyAndForwardLoginsResult,
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 this, base::Owned(request));
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScheduleTask(base::Bind(&PasswordStore::GetLoginsImpl,
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          this, form, prompt_policy, callback_runner));
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Schedule(&PasswordStore::GetAutofillableLoginsImpl, consumer);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::GetBlacklistLogins(PasswordStoreConsumer* consumer) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Schedule(&PasswordStore::GetBlacklistLoginsImpl, consumer);
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PasswordStore::ReportMetrics(const std::string& sync_username) {
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScheduleTask(base::Bind(&PasswordStore::ReportMetricsImpl, this,
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          sync_username));
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::AddObserver(Observer* observer) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observers_->AddObserver(observer);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::RemoveObserver(Observer* observer) {
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observers_->RemoveObserver(observer);
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool PasswordStore::ScheduleTask(const base::Closure& task) {
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> task_runner(
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GetBackgroundTaskRunner());
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (task_runner.get())
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return task_runner->PostTask(FROM_HERE, task);
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return false;
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PasswordStore::Shutdown() {
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScheduleTask(base::Bind(&PasswordStore::DestroySyncableService, this));
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  shutdown_called_ = true;
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::WeakPtr<syncer::SyncableService>
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PasswordStore::GetPasswordSyncableService() {
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(syncable_service_);
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return syncable_service_->AsWeakPtr();
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStore::~PasswordStore() { DCHECK(shutdown_called_); }
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<base::SingleThreadTaskRunner>
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PasswordStore::GetBackgroundTaskRunner() {
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return db_thread_runner_;
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::ForwardLoginsResult(GetLoginsRequest* request) {
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->ApplyIgnoreLoginsCutoff();
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->ForwardResult();
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::CopyAndForwardLoginsResult(
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStore::GetLoginsRequest* request,
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::vector<PasswordForm*>& matched_forms) {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Copy the contents of |matched_forms| into the request. The request takes
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ownership of the PasswordForm elements.
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *(request->result()) = matched_forms;
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ForwardLoginsResult(request);
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::LogStatsForBulkDeletion(int num_deletions) {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedByBulkDelete",
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       num_deletions);
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void PasswordStore::NotifyLoginsChanged(
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const PasswordStoreChangeList& changes) {
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!changes.empty()) {
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    observers_->Notify(&Observer::OnLoginsChanged, changes);
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (syncable_service_)
2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      syncable_service_->ActOnPasswordStoreChanges(changes);
2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<typename BackendFunc>
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::Schedule(
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BackendFunc func,
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PasswordStoreConsumer* consumer) {
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetLoginsRequest* request = new GetLoginsRequest(consumer);
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  consumer->cancelable_task_tracker()->PostTask(
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetBackgroundTaskRunner().get(),
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(func, this, base::Owned(request)));
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PasswordStore::WrapModificationTask(ModificationTask task) {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PasswordStoreChangeList changes = task.Run();
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyLoginsChanged(changes);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PasswordStore::InitSyncableService(
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const syncer::SyncableService::StartSyncFlare& flare) {
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!syncable_service_);
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  syncable_service_.reset(new PasswordSyncableService(this));
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  syncable_service_->InjectStartSyncFlare(flare);
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PasswordStore::DestroySyncableService() {
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  syncable_service_.reset();
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace password_manager
284