[Password Manager] Remove NOTIFICATION_LOGINS_CHANGED
[chromium-blink-merge.git] / chrome / browser / password_manager / password_store.cc
blobc1f72fd255cc4e05ed9cfcfc5e6bdd92374e509f
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 observers_(new ObserverListThreadSafe<Observer>()),
73 shutdown_called_(false) {}
75 bool PasswordStore::Init() {
76 ReportMetrics();
77 return true;
80 void PasswordStore::AddLogin(const PasswordForm& form) {
81 ScheduleTask(
82 base::Bind(&PasswordStore::WrapModificationTask, this,
83 base::Bind(&PasswordStore::AddLoginImpl, this, form)));
86 void PasswordStore::UpdateLogin(const PasswordForm& form) {
87 ScheduleTask(
88 base::Bind(&PasswordStore::WrapModificationTask, this,
89 base::Bind(&PasswordStore::UpdateLoginImpl, this, form)));
92 void PasswordStore::RemoveLogin(const PasswordForm& form) {
93 ScheduleTask(
94 base::Bind(&PasswordStore::WrapModificationTask, this,
95 base::Bind(&PasswordStore::RemoveLoginImpl, this, form)));
98 void PasswordStore::RemoveLoginsCreatedBetween(const base::Time& delete_begin,
99 const base::Time& delete_end) {
100 ScheduleTask(
101 base::Bind(&PasswordStore::WrapModificationTask, this,
102 base::Bind(&PasswordStore::RemoveLoginsCreatedBetweenImpl,
103 this, delete_begin, delete_end)));
106 void PasswordStore::GetLogins(
107 const PasswordForm& form,
108 AuthorizationPromptPolicy prompt_policy,
109 PasswordStoreConsumer* consumer) {
110 // Per http://crbug.com/121738, we deliberately ignore saved logins for
111 // http*://www.google.com/ that were stored prior to 2012. (Google now uses
112 // https://accounts.google.com/ for all login forms, so these should be
113 // unused.) We don't delete them just yet, and they'll still be visible in the
114 // password manager, but we won't use them to autofill any forms. This is a
115 // security feature to help minimize damage that can be done by XSS attacks.
116 // TODO(mdm): actually delete them at some point, say M24 or so.
117 base::Time ignore_logins_cutoff; // the null time
118 if (form.scheme == PasswordForm::SCHEME_HTML &&
119 (form.signon_realm == "http://www.google.com" ||
120 form.signon_realm == "http://www.google.com/" ||
121 form.signon_realm == "https://www.google.com" ||
122 form.signon_realm == "https://www.google.com/")) {
123 static const base::Time::Exploded exploded_cutoff =
124 { 2012, 1, 0, 1, 0, 0, 0, 0 }; // 00:00 Jan 1 2012
125 ignore_logins_cutoff = base::Time::FromUTCExploded(exploded_cutoff);
127 GetLoginsRequest* request = new GetLoginsRequest(consumer);
128 request->set_ignore_logins_cutoff(ignore_logins_cutoff);
130 ConsumerCallbackRunner callback_runner =
131 base::Bind(&PasswordStore::CopyAndForwardLoginsResult,
132 this, base::Owned(request));
133 ScheduleTask(base::Bind(&PasswordStore::GetLoginsImpl,
134 this, form, prompt_policy, callback_runner));
137 void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
138 Schedule(&PasswordStore::GetAutofillableLoginsImpl, consumer);
141 void PasswordStore::GetBlacklistLogins(PasswordStoreConsumer* consumer) {
142 Schedule(&PasswordStore::GetBlacklistLoginsImpl, consumer);
145 void PasswordStore::ReportMetrics() {
146 ScheduleTask(base::Bind(&PasswordStore::ReportMetricsImpl, this));
149 void PasswordStore::AddObserver(Observer* observer) {
150 observers_->AddObserver(observer);
153 void PasswordStore::RemoveObserver(Observer* observer) {
154 observers_->RemoveObserver(observer);
157 void PasswordStore::Shutdown() { shutdown_called_ = true; }
159 PasswordStore::~PasswordStore() { DCHECK(shutdown_called_); }
161 bool PasswordStore::ScheduleTask(const base::Closure& task) {
162 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
163 GetBackgroundTaskRunner());
164 if (task_runner.get())
165 return task_runner->PostTask(FROM_HERE, task);
166 return false;
169 scoped_refptr<base::SingleThreadTaskRunner>
170 PasswordStore::GetBackgroundTaskRunner() {
171 return db_thread_runner_;
174 void PasswordStore::ForwardLoginsResult(GetLoginsRequest* request) {
175 request->ApplyIgnoreLoginsCutoff();
176 request->ForwardResult();
179 void PasswordStore::CopyAndForwardLoginsResult(
180 PasswordStore::GetLoginsRequest* request,
181 const vector<PasswordForm*>& matched_forms) {
182 // Copy the contents of |matched_forms| into the request. The request takes
183 // ownership of the PasswordForm elements.
184 *(request->result()) = matched_forms;
185 ForwardLoginsResult(request);
188 void PasswordStore::LogStatsForBulkDeletion(int num_deletions) {
189 UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedByBulkDelete",
190 num_deletions);
193 template<typename BackendFunc>
194 void PasswordStore::Schedule(
195 BackendFunc func,
196 PasswordStoreConsumer* consumer) {
197 GetLoginsRequest* request = new GetLoginsRequest(consumer);
198 consumer->cancelable_task_tracker()->PostTask(
199 GetBackgroundTaskRunner(),
200 FROM_HERE,
201 base::Bind(func, this, base::Owned(request)));
204 void PasswordStore::WrapModificationTask(ModificationTask task) {
205 PasswordStoreChangeList changes = task.Run();
206 NotifyLoginsChanged(changes);
209 void PasswordStore::NotifyLoginsChanged(
210 const PasswordStoreChangeList& changes) {
211 if (!changes.empty())
212 observers_->Notify(&Observer::OnLoginsChanged, changes);