Remove the dependency of PasswordStore on BrowserContextKeyedService
[chromium-blink-merge.git] / chrome / browser / password_manager / password_store.cc
blob909c492343d7d633dde6c72bc0f60fd5ff7d2576
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/password_manager/password_store.h"
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/metrics/histogram.h"
12 #include "base/stl_util.h"
13 #include "chrome/browser/password_manager/password_store_consumer.h"
14 #include "components/autofill/core/common/password_form.h"
16 using autofill::PasswordForm;
17 using std::vector;
19 namespace {
21 // Calls |consumer| back with the request result, if |consumer| is still alive.
22 // Takes ownership of the elements in |result|, passing ownership to |consumer|
23 // if it is still alive.
24 void MaybeCallConsumerCallback(base::WeakPtr<PasswordStoreConsumer> consumer,
25 scoped_ptr<vector<PasswordForm*> > result) {
26 if (consumer.get())
27 consumer->OnGetPasswordStoreResults(*result);
28 else
29 STLDeleteElements(result.get());
32 } // namespace
34 PasswordStore::GetLoginsRequest::GetLoginsRequest(
35 PasswordStoreConsumer* consumer)
36 : consumer_weak_(consumer->GetWeakPtr()),
37 result_(new vector<PasswordForm*>()) {
38 DCHECK(thread_checker_.CalledOnValidThread());
39 origin_loop_ = base::MessageLoopProxy::current();
42 PasswordStore::GetLoginsRequest::~GetLoginsRequest() {
45 void PasswordStore::GetLoginsRequest::ApplyIgnoreLoginsCutoff() {
46 if (!ignore_logins_cutoff_.is_null()) {
47 // Count down rather than up since we may be deleting elements.
48 // Note that in principle it could be more efficient to copy the whole array
49 // since that's worst-case linear time, but we expect that elements will be
50 // deleted rarely and lists will be small, so this avoids the copies.
51 for (size_t i = result_->size(); i > 0; --i) {
52 if ((*result_)[i - 1]->date_created < ignore_logins_cutoff_) {
53 delete (*result_)[i - 1];
54 result_->erase(result_->begin() + (i - 1));
60 void PasswordStore::GetLoginsRequest::ForwardResult() {
61 origin_loop_->PostTask(FROM_HERE,
62 base::Bind(&MaybeCallConsumerCallback,
63 consumer_weak_,
64 base::Passed(result_.Pass())));
67 PasswordStore::PasswordStore(
68 scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
69 scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner)
70 : main_thread_runner_(main_thread_runner),
71 db_thread_runner_(db_thread_runner),
72 shutdown_called_(false) {}
74 bool PasswordStore::Init() {
75 ReportMetrics();
76 return true;
79 void PasswordStore::AddLogin(const PasswordForm& form) {
80 ScheduleTask(base::Bind(&PasswordStore::WrapModificationTask, this,
81 base::Closure(base::Bind(&PasswordStore::AddLoginImpl, this, form))));
84 void PasswordStore::UpdateLogin(const PasswordForm& form) {
85 ScheduleTask(base::Bind(&PasswordStore::WrapModificationTask, this,
86 base::Closure(base::Bind(&PasswordStore::UpdateLoginImpl, this, form))));
89 void PasswordStore::RemoveLogin(const PasswordForm& form) {
90 ScheduleTask(base::Bind(&PasswordStore::WrapModificationTask, this,
91 base::Closure(base::Bind(&PasswordStore::RemoveLoginImpl, this, form))));
94 void PasswordStore::RemoveLoginsCreatedBetween(const base::Time& delete_begin,
95 const base::Time& delete_end) {
96 ScheduleTask(base::Bind(&PasswordStore::WrapModificationTask, this,
97 base::Closure(
98 base::Bind(&PasswordStore::RemoveLoginsCreatedBetweenImpl, this,
99 delete_begin, delete_end))));
102 void PasswordStore::GetLogins(
103 const PasswordForm& form,
104 AuthorizationPromptPolicy prompt_policy,
105 PasswordStoreConsumer* consumer) {
106 // Per http://crbug.com/121738, we deliberately ignore saved logins for
107 // http*://www.google.com/ that were stored prior to 2012. (Google now uses
108 // https://accounts.google.com/ for all login forms, so these should be
109 // unused.) We don't delete them just yet, and they'll still be visible in the
110 // password manager, but we won't use them to autofill any forms. This is a
111 // security feature to help minimize damage that can be done by XSS attacks.
112 // TODO(mdm): actually delete them at some point, say M24 or so.
113 base::Time ignore_logins_cutoff; // the null time
114 if (form.scheme == PasswordForm::SCHEME_HTML &&
115 (form.signon_realm == "http://www.google.com" ||
116 form.signon_realm == "http://www.google.com/" ||
117 form.signon_realm == "https://www.google.com" ||
118 form.signon_realm == "https://www.google.com/")) {
119 static const base::Time::Exploded exploded_cutoff =
120 { 2012, 1, 0, 1, 0, 0, 0, 0 }; // 00:00 Jan 1 2012
121 ignore_logins_cutoff = base::Time::FromUTCExploded(exploded_cutoff);
123 GetLoginsRequest* request = new GetLoginsRequest(consumer);
124 request->set_ignore_logins_cutoff(ignore_logins_cutoff);
126 ConsumerCallbackRunner callback_runner =
127 base::Bind(&PasswordStore::CopyAndForwardLoginsResult,
128 this, base::Owned(request));
129 ScheduleTask(base::Bind(&PasswordStore::GetLoginsImpl,
130 this, form, prompt_policy, callback_runner));
133 void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
134 Schedule(&PasswordStore::GetAutofillableLoginsImpl, consumer);
137 void PasswordStore::GetBlacklistLogins(PasswordStoreConsumer* consumer) {
138 Schedule(&PasswordStore::GetBlacklistLoginsImpl, consumer);
141 void PasswordStore::ReportMetrics() {
142 ScheduleTask(base::Bind(&PasswordStore::ReportMetricsImpl, this));
145 void PasswordStore::AddObserver(Observer* observer) {
146 observers_.AddObserver(observer);
149 void PasswordStore::RemoveObserver(Observer* observer) {
150 observers_.RemoveObserver(observer);
153 void PasswordStore::Shutdown() { shutdown_called_ = true; }
155 PasswordStore::~PasswordStore() { DCHECK(shutdown_called_); }
157 bool PasswordStore::ScheduleTask(const base::Closure& task) {
158 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
159 GetBackgroundTaskRunner());
160 if (task_runner.get())
161 return task_runner->PostTask(FROM_HERE, task);
162 return false;
165 scoped_refptr<base::SingleThreadTaskRunner>
166 PasswordStore::GetBackgroundTaskRunner() {
167 return db_thread_runner_;
170 void PasswordStore::ForwardLoginsResult(GetLoginsRequest* request) {
171 request->ApplyIgnoreLoginsCutoff();
172 request->ForwardResult();
175 void PasswordStore::CopyAndForwardLoginsResult(
176 PasswordStore::GetLoginsRequest* request,
177 const vector<PasswordForm*>& matched_forms) {
178 // Copy the contents of |matched_forms| into the request. The request takes
179 // ownership of the PasswordForm elements.
180 *(request->result()) = matched_forms;
181 ForwardLoginsResult(request);
184 void PasswordStore::LogStatsForBulkDeletion(int num_deletions) {
185 UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedByBulkDelete",
186 num_deletions);
189 template<typename BackendFunc>
190 void PasswordStore::Schedule(
191 BackendFunc func,
192 PasswordStoreConsumer* consumer) {
193 GetLoginsRequest* request = new GetLoginsRequest(consumer);
194 consumer->cancelable_task_tracker()->PostTask(
195 GetBackgroundTaskRunner(),
196 FROM_HERE,
197 base::Bind(func, this, base::Owned(request)));
200 void PasswordStore::WrapModificationTask(base::Closure task) {
201 task.Run();
202 PostNotifyLoginsChanged();
205 void PasswordStore::PostNotifyLoginsChanged() {
206 main_thread_runner_->PostTask(
207 FROM_HERE,
208 base::Bind(&PasswordStore::NotifyLoginsChanged, this));
211 void PasswordStore::NotifyLoginsChanged() {
212 DCHECK(main_thread_runner_->BelongsToCurrentThread());
213 FOR_EACH_OBSERVER(Observer, observers_, OnLoginsChanged());