1 // Copyright 2014 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.
4
5 #include "components/password_manager/core/browser/password_store.h"
6
7 #include <algorithm>
8 #include <iterator>
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/debug/dump_without_crashing.h"
15 #include "base/location.h"
16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/metrics/histogram_functions.h"
19 #include "base/metrics/histogram_macros.h"
20 #include "base/stl_util.h"
21 #include "base/task/post_task.h"
22 #include "base/task/thread_pool.h"
23 #include "base/task_runner_util.h"
24 #include "base/threading/sequenced_task_runner_handle.h"
25 #include "base/trace_event/trace_event.h"
26 #include "build/build_config.h"
27 #include "components/autofill/core/common/form_data.h"
28 #include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h"
29 #include "components/password_manager/core/browser/compromised_credentials_consumer.h"
30 #include "components/password_manager/core/browser/compromised_credentials_observer.h"
31 #include "components/password_manager/core/browser/compromised_credentials_table.h"
32 #include "components/password_manager/core/browser/field_info_table.h"
33 #include "components/password_manager/core/browser/password_form.h"
34 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
35 #include "components/password_manager/core/browser/password_manager_util.h"
36 #include "components/password_manager/core/browser/password_store_consumer.h"
37 #include "components/password_manager/core/browser/statistics_table.h"
38 #include "components/password_manager/core/browser/sync/password_sync_bridge.h"
39 #include "components/password_manager/core/common/password_manager_pref_names.h"
40 #include "components/prefs/pref_service.h"
41 #include "components/sync/model_impl/client_tag_based_model_type_processor.h"
42 #include "components/sync/model_impl/proxy_model_type_controller_delegate.h"
43 #include "base/strings/string16.h"
44 #include "components/password_manager/core/browser/password_store_signin_notifier.h"
45 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
46
47 namespace password_manager {
48
49 namespace {
50
51 // Utility function to simplify removing logins prior a given |cutoff| data.
52 // Runs |callback| with the result.
53 //
54 // TODO(http://crbug.com/121738): Remove this once filtering logins is no longer
55 // necessary.
FilterLogins(base::Time cutoff,base::OnceCallback<void (std::vector<std::unique_ptr<PasswordForm>>)> callback,std::vector<std::unique_ptr<PasswordForm>> logins)56 void FilterLogins(
57 base::Time cutoff,
58 base::OnceCallback<void(std::vector<std::unique_ptr<PasswordForm>>)>
59 callback,
60 std::vector<std::unique_ptr<PasswordForm>> logins) {
61 base::EraseIf(logins, [cutoff](const auto& form) {
62 return form->date_created < cutoff;
63 });
64
65 std::move(callback).Run(std::move(logins));
66 }
67
CloseTraceAndCallBack(const char * trace_name,PasswordStoreConsumer * consumer,base::OnceCallback<void (std::vector<std::unique_ptr<PasswordForm>>)> callback,std::vector<std::unique_ptr<PasswordForm>> results)68 void CloseTraceAndCallBack(
69 const char* trace_name,
70 PasswordStoreConsumer* consumer,
71 base::OnceCallback<void(std::vector<std::unique_ptr<PasswordForm>>)>
72 callback,
73 std::vector<std::unique_ptr<PasswordForm>> results) {
74 TRACE_EVENT_NESTABLE_ASYNC_END0("passwords", trace_name, consumer);
75
76 std::move(callback).Run(std::move(results));
77 }
78
79 } // namespace
80
OnLoginsChangedIn(PasswordStore * store,const PasswordStoreChangeList & changes)81 void PasswordStore::Observer::OnLoginsChangedIn(
82 PasswordStore* store,
83 const PasswordStoreChangeList& changes) {
84 OnLoginsChanged(changes);
85 }
86
87 void PasswordStore::DatabaseCompromisedCredentialsObserver::
OnCompromisedCredentialsChangedIn(PasswordStore * store)88 OnCompromisedCredentialsChangedIn(PasswordStore* store) {
89 OnCompromisedCredentialsChanged();
90 }
91
CheckReuseRequest(PasswordReuseDetectorConsumer * consumer)92 PasswordStore::CheckReuseRequest::CheckReuseRequest(
93 PasswordReuseDetectorConsumer* consumer)
94 : origin_task_runner_(base::SequencedTaskRunnerHandle::Get()),
95 consumer_weak_(consumer->AsWeakPtr()) {
96 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("passwords", "CheckReuseRequest", this);
97 }
98
99 PasswordStore::CheckReuseRequest::~CheckReuseRequest() = default;
100
OnReuseCheckDone(bool is_reuse_found,size_t password_length,base::Optional<PasswordHashData> reused_protected_password_hash,const std::vector<MatchingReusedCredential> & matching_reused_credentials,int saved_passwords)101 void PasswordStore::CheckReuseRequest::OnReuseCheckDone(
102 bool is_reuse_found,
103 size_t password_length,
104 base::Optional<PasswordHashData> reused_protected_password_hash,
105 const std::vector<MatchingReusedCredential>& matching_reused_credentials,
106 int saved_passwords) {
107 origin_task_runner_->PostTask(
108 FROM_HERE,
109 base::BindOnce(&PasswordReuseDetectorConsumer::OnReuseCheckDone,
110 consumer_weak_, is_reuse_found, password_length,
111 reused_protected_password_hash,
112 matching_reused_credentials, saved_passwords));
113 TRACE_EVENT_NESTABLE_ASYNC_END0("passwords", "CheckReuseRequest", this);
114 }
115
FormDigest(PasswordForm::Scheme new_scheme,const std::string & new_signon_realm,const GURL & new_url)116 PasswordStore::FormDigest::FormDigest(PasswordForm::Scheme new_scheme,
117 const std::string& new_signon_realm,
118 const GURL& new_url)
119 : scheme(new_scheme), signon_realm(new_signon_realm), url(new_url) {}
120
FormDigest(const PasswordForm & form)121 PasswordStore::FormDigest::FormDigest(const PasswordForm& form)
122 : scheme(form.scheme), signon_realm(form.signon_realm), url(form.url) {}
123
FormDigest(const autofill::FormData & form)124 PasswordStore::FormDigest::FormDigest(const autofill::FormData& form)
125 : scheme(PasswordForm::Scheme::kHtml),
126 signon_realm(form.url.GetOrigin().spec()),
127 url(form.url) {}
128
129 PasswordStore::FormDigest::FormDigest(const FormDigest& other) = default;
130
131 PasswordStore::FormDigest::FormDigest(FormDigest&& other) = default;
132
133 PasswordStore::FormDigest& PasswordStore::FormDigest::operator=(
134 const FormDigest& other) = default;
135
136 PasswordStore::FormDigest& PasswordStore::FormDigest::operator=(
137 FormDigest&& other) = default;
138
operator ==(const FormDigest & other) const139 bool PasswordStore::FormDigest::operator==(const FormDigest& other) const {
140 return scheme == other.scheme && signon_realm == other.signon_realm &&
141 url == other.url;
142 }
143
operator !=(const FormDigest & other) const144 bool PasswordStore::FormDigest::operator!=(const FormDigest& other) const {
145 return !(*this == other);
146 }
147
PasswordStore()148 PasswordStore::PasswordStore()
149 : observers_(new base::ObserverListThreadSafe<Observer>()) {}
150
Init(PrefService * prefs,base::RepeatingClosure sync_enabled_or_disabled_cb)151 bool PasswordStore::Init(PrefService* prefs,
152 base::RepeatingClosure sync_enabled_or_disabled_cb) {
153 main_task_runner_ = base::SequencedTaskRunnerHandle::Get();
154 DCHECK(main_task_runner_);
155 background_task_runner_ = CreateBackgroundTaskRunner();
156 DCHECK(background_task_runner_);
157 sync_enabled_or_disabled_cb_ = std::move(sync_enabled_or_disabled_cb);
158 prefs_ = prefs;
159 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
160 hash_password_manager_.set_prefs(prefs);
161 #endif
162 if (background_task_runner_) {
163 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
164 "passwords", "PasswordStore::InitOnBackgroundSequence", this);
165 base::PostTaskAndReplyWithResult(
166 background_task_runner_.get(), FROM_HERE,
167 base::BindOnce(&PasswordStore::InitOnBackgroundSequence, this),
168 base::BindOnce(&PasswordStore::OnInitCompleted, this));
169 }
170
171 return true;
172 }
173
SetAffiliatedMatchHelper(std::unique_ptr<AffiliatedMatchHelper> helper)174 void PasswordStore::SetAffiliatedMatchHelper(
175 std::unique_ptr<AffiliatedMatchHelper> helper) {
176 affiliated_match_helper_ = std::move(helper);
177 }
178
AddLogin(const PasswordForm & form)179 void PasswordStore::AddLogin(const PasswordForm& form) {
180 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
181 ScheduleTask(base::BindOnce(&PasswordStore::AddLoginInternal, this, form));
182 }
183
UpdateLogin(const PasswordForm & form)184 void PasswordStore::UpdateLogin(const PasswordForm& form) {
185 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
186 ScheduleTask(base::BindOnce(&PasswordStore::UpdateLoginInternal, this, form));
187 }
188
UpdateLoginWithPrimaryKey(const PasswordForm & new_form,const PasswordForm & old_primary_key)189 void PasswordStore::UpdateLoginWithPrimaryKey(
190 const PasswordForm& new_form,
191 const PasswordForm& old_primary_key) {
192 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
193 ScheduleTask(base::BindOnce(&PasswordStore::UpdateLoginWithPrimaryKeyInternal,
194 this, new_form, old_primary_key));
195 }
196
RemoveLogin(const PasswordForm & form)197 void PasswordStore::RemoveLogin(const PasswordForm& form) {
198 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
199 ScheduleTask(base::BindOnce(&PasswordStore::RemoveLoginInternal, this, form));
200 }
201
RemoveLoginsByURLAndTime(const base::RepeatingCallback<bool (const GURL &)> & url_filter,base::Time delete_begin,base::Time delete_end,base::OnceClosure completion,base::OnceCallback<void (bool)> sync_completion)202 void PasswordStore::RemoveLoginsByURLAndTime(
203 const base::RepeatingCallback<bool(const GURL&)>& url_filter,
204 base::Time delete_begin,
205 base::Time delete_end,
206 base::OnceClosure completion,
207 base::OnceCallback<void(bool)> sync_completion) {
208 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
209 ScheduleTask(base::BindOnce(&PasswordStore::RemoveLoginsByURLAndTimeInternal,
210 this, url_filter, delete_begin, delete_end,
211 std::move(completion),
212 std::move(sync_completion)));
213 }
214
RemoveLoginsCreatedBetween(base::Time delete_begin,base::Time delete_end,base::OnceClosure completion)215 void PasswordStore::RemoveLoginsCreatedBetween(base::Time delete_begin,
216 base::Time delete_end,
217 base::OnceClosure completion) {
218 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
219 ScheduleTask(
220 base::BindOnce(&PasswordStore::RemoveLoginsCreatedBetweenInternal, this,
221 delete_begin, delete_end, std::move(completion)));
222 }
223
RemoveStatisticsByOriginAndTime(const base::RepeatingCallback<bool (const GURL &)> & origin_filter,base::Time delete_begin,base::Time delete_end,base::OnceClosure completion)224 void PasswordStore::RemoveStatisticsByOriginAndTime(
225 const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
226 base::Time delete_begin,
227 base::Time delete_end,
228 base::OnceClosure completion) {
229 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
230 ScheduleTask(base::BindOnce(
231 &PasswordStore::RemoveStatisticsByOriginAndTimeInternal, this,
232 origin_filter, delete_begin, delete_end, std::move(completion)));
233 }
234
DisableAutoSignInForOrigins(const base::RepeatingCallback<bool (const GURL &)> & origin_filter,base::OnceClosure completion)235 void PasswordStore::DisableAutoSignInForOrigins(
236 const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
237 base::OnceClosure completion) {
238 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
239 ScheduleTask(
240 base::BindOnce(&PasswordStore::DisableAutoSignInForOriginsInternal, this,
241 base::RepeatingCallback<bool(const GURL&)>(origin_filter),
242 std::move(completion)));
243 }
244
Unblacklist(const PasswordStore::FormDigest & form_digest,base::OnceClosure completion)245 void PasswordStore::Unblacklist(const PasswordStore::FormDigest& form_digest,
246 base::OnceClosure completion) {
247 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
248 ScheduleTask(base::BindOnce(&PasswordStore::UnblacklistInternal, this,
249 form_digest, std::move(completion)));
250 }
251
GetLogins(const FormDigest & form,PasswordStoreConsumer * consumer)252 void PasswordStore::GetLogins(const FormDigest& form,
253 PasswordStoreConsumer* consumer) {
254 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
255 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("passwords", "PasswordStore::GetLogins",
256 consumer);
257 // Per http://crbug.com/121738, we deliberately ignore saved logins for
258 // http*://www.google.com/ that were stored prior to 2012. (Google now uses
259 // https://accounts.google.com/ for all login forms, so these should be
260 // unused.) We don't delete them just yet, and they'll still be visible in the
261 // password manager, but we won't use them to autofill any forms. This is a
262 // security feature to help minimize damage that can be done by XSS attacks.
263 // TODO(mdm): actually delete them at some point, say M24 or so.
264 base::Time cutoff; // the null time
265 if (form.scheme == PasswordForm::Scheme::kHtml &&
266 (form.signon_realm == "http://www.google.com" ||
267 form.signon_realm == "http://www.google.com/" ||
268 form.signon_realm == "https://www.google.com" ||
269 form.signon_realm == "https://www.google.com/")) {
270 static const base::Time::Exploded exploded_cutoff = {
271 2012, 1, 0, 1, 0, 0, 0, 0}; // 00:00 Jan 1 2012
272 base::Time out_time;
273 bool conversion_success =
274 base::Time::FromUTCExploded(exploded_cutoff, &out_time);
275 DCHECK(conversion_success);
276 cutoff = out_time;
277 }
278
279 if (affiliated_match_helper_) {
280 affiliated_match_helper_->GetAffiliatedAndroidRealms(
281 form, base::BindOnce(
282 &PasswordStore::ScheduleGetFilteredLoginsWithAffiliations,
283 this, consumer->GetWeakPtr(), form, cutoff));
284 } else {
285 PostLoginsTaskAndReplyToConsumerWithProcessedResult(
286 "PasswordStore::GetLogins", consumer,
287 base::BindOnce(&PasswordStore::GetLoginsImpl, this, form),
288 base::BindOnce(FilterLogins, cutoff));
289 }
290 }
291
GetLoginsByPassword(const base::string16 & plain_text_password,PasswordStoreConsumer * consumer)292 void PasswordStore::GetLoginsByPassword(
293 const base::string16& plain_text_password,
294 PasswordStoreConsumer* consumer) {
295 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
296 PostLoginsTaskAndReplyToConsumerWithResult(
297 consumer, base::BindOnce(&PasswordStore::GetLoginsByPasswordImpl, this,
298 plain_text_password));
299 }
300
GetAutofillableLogins(PasswordStoreConsumer * consumer)301 void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
302 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
303 PostLoginsTaskAndReplyToConsumerWithResult(
304 consumer,
305 base::BindOnce(&PasswordStore::GetAutofillableLoginsImpl, this));
306 }
307
GetAllLogins(PasswordStoreConsumer * consumer)308 void PasswordStore::GetAllLogins(PasswordStoreConsumer* consumer) {
309 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
310 PostLoginsTaskAndReplyToConsumerWithResult(
311 consumer, base::BindOnce(&PasswordStore::GetAllLoginsImpl, this));
312 }
313
GetAllLoginsWithAffiliationAndBrandingInformation(PasswordStoreConsumer * consumer)314 void PasswordStore::GetAllLoginsWithAffiliationAndBrandingInformation(
315 PasswordStoreConsumer* consumer) {
316 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
317 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
318 "passwords",
319 "PasswordStore::GetAllLoginsWithAffiliationAndBrandingInformation",
320 consumer);
321 PostLoginsTaskAndReplyToConsumerWithProcessedResult(
322 "PasswordStore::GetAllLoginsWithAffiliationAndBrandingInformation",
323 consumer, base::BindOnce(&PasswordStore::GetAllLoginsImpl, this),
324 base::BindOnce(&PasswordStore::InjectAffiliationAndBrandingInformation,
325 this));
326 }
327
ReportMetrics(const std::string & sync_username,bool custom_passphrase_sync_enabled,bool is_under_advanced_protection)328 void PasswordStore::ReportMetrics(const std::string& sync_username,
329 bool custom_passphrase_sync_enabled,
330 bool is_under_advanced_protection) {
331 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
332 if (background_task_runner_) {
333 base::OnceClosure task = base::BindOnce(
334 &PasswordStore::ReportMetricsImpl, this, sync_username,
335 custom_passphrase_sync_enabled,
336 BulkCheckDone(prefs_ && prefs_->HasPrefPath(
337 prefs::kLastTimePasswordCheckCompleted)));
338 background_task_runner_->PostDelayedTask(FROM_HERE, std::move(task),
339 base::TimeDelta::FromSeconds(30));
340 }
341
342 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
343 if (!sync_username.empty()) {
344 auto hash_password_state =
345 hash_password_manager_.HasPasswordHash(sync_username,
346 /*is_gaia_password=*/true)
347 ? metrics_util::IsSyncPasswordHashSaved::SAVED_VIA_LIST_PREF
348 : metrics_util::IsSyncPasswordHashSaved::NOT_SAVED;
349 metrics_util::LogIsSyncPasswordHashSaved(hash_password_state,
350 is_under_advanced_protection);
351 }
352 #endif
353 }
354
AddSiteStats(const InteractionsStats & stats)355 void PasswordStore::AddSiteStats(const InteractionsStats& stats) {
356 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
357 ScheduleTask(base::BindOnce(&PasswordStore::AddSiteStatsImpl, this, stats));
358 }
359
RemoveSiteStats(const GURL & origin_domain)360 void PasswordStore::RemoveSiteStats(const GURL& origin_domain) {
361 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
362 ScheduleTask(
363 base::BindOnce(&PasswordStore::RemoveSiteStatsImpl, this, origin_domain));
364 }
365
GetSiteStats(const GURL & origin_domain,PasswordStoreConsumer * consumer)366 void PasswordStore::GetSiteStats(const GURL& origin_domain,
367 PasswordStoreConsumer* consumer) {
368 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
369 PostStatsTaskAndReplyToConsumerWithResult(
370 consumer,
371 base::BindOnce(&PasswordStore::GetSiteStatsImpl, this, origin_domain));
372 }
373
AddCompromisedCredentials(const CompromisedCredentials & compromised_credentials)374 void PasswordStore::AddCompromisedCredentials(
375 const CompromisedCredentials& compromised_credentials) {
376 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
377 auto callback = base::BindOnce(&PasswordStore::AddCompromisedCredentialsImpl,
378 this, compromised_credentials);
379 ScheduleTask(base::BindOnce(
380 &PasswordStore::InvokeAndNotifyAboutCompromisedPasswordsChange, this,
381 std::move(callback)));
382 }
383
RemoveCompromisedCredentials(const std::string & signon_realm,const base::string16 & username,RemoveCompromisedCredentialsReason reason)384 void PasswordStore::RemoveCompromisedCredentials(
385 const std::string& signon_realm,
386 const base::string16& username,
387 RemoveCompromisedCredentialsReason reason) {
388 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
389 auto callback =
390 base::BindOnce(&PasswordStore::RemoveCompromisedCredentialsImpl, this,
391 signon_realm, username, reason);
392 ScheduleTask(base::BindOnce(
393 &PasswordStore::InvokeAndNotifyAboutCompromisedPasswordsChange, this,
394 std::move(callback)));
395 }
396
RemoveCompromisedCredentialsByCompromiseType(const std::string & signon_realm,const base::string16 & username,const CompromiseType & compromise_type,RemoveCompromisedCredentialsReason reason)397 void PasswordStore::RemoveCompromisedCredentialsByCompromiseType(
398 const std::string& signon_realm,
399 const base::string16& username,
400 const CompromiseType& compromise_type,
401 RemoveCompromisedCredentialsReason reason) {
402 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
403 auto callback = base::BindOnce(
404 &PasswordStore::RemoveCompromisedCredentialsByCompromiseTypeImpl, this,
405 signon_realm, username, compromise_type, reason);
406 ScheduleTask(base::BindOnce(
407 &PasswordStore::InvokeAndNotifyAboutCompromisedPasswordsChange, this,
408 std::move(callback)));
409 }
410
GetAllCompromisedCredentials(CompromisedCredentialsConsumer * consumer)411 void PasswordStore::GetAllCompromisedCredentials(
412 CompromisedCredentialsConsumer* consumer) {
413 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
414 PostCompromisedCredentialsTaskAndReplyToConsumerWithResult(
415 consumer,
416 base::BindOnce(&PasswordStore::GetAllCompromisedCredentialsImpl, this));
417 }
418
GetMatchingCompromisedCredentials(const std::string & signon_realm,CompromisedCredentialsConsumer * consumer)419 void PasswordStore::GetMatchingCompromisedCredentials(
420 const std::string& signon_realm,
421 CompromisedCredentialsConsumer* consumer) {
422 if (affiliated_match_helper_) {
423 FormDigest form(PasswordForm::Scheme::kHtml, signon_realm,
424 GURL(signon_realm));
425 affiliated_match_helper_->GetAffiliatedAndroidRealms(
426 form,
427 base::BindOnce(&PasswordStore::ScheduleGetCompromisedWithAffiliations,
428 this, consumer->GetWeakPtr(), signon_realm));
429 } else {
430 PostCompromisedCredentialsTaskAndReplyToConsumerWithResult(
431 consumer,
432 base::BindOnce(&PasswordStore::GetMatchingCompromisedCredentialsImpl,
433 this, signon_realm));
434 }
435 }
436
RemoveCompromisedCredentialsByUrlAndTime(base::RepeatingCallback<bool (const GURL &)> url_filter,base::Time remove_begin,base::Time remove_end,base::OnceClosure completion)437 void PasswordStore::RemoveCompromisedCredentialsByUrlAndTime(
438 base::RepeatingCallback<bool(const GURL&)> url_filter,
439 base::Time remove_begin,
440 base::Time remove_end,
441 base::OnceClosure completion) {
442 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
443 auto callback = base::BindOnce(
444 &PasswordStore::RemoveCompromisedCredentialsByUrlAndTimeInternal, this,
445 std::move(url_filter), remove_begin, remove_end, std::move(completion));
446
447 ScheduleTask(base::BindOnce(
448 &PasswordStore::InvokeAndNotifyAboutCompromisedPasswordsChange, this,
449 std::move(callback)));
450 }
451
AddFieldInfo(const FieldInfo & field_info)452 void PasswordStore::AddFieldInfo(const FieldInfo& field_info) {
453 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
454 ScheduleTask(
455 base::BindOnce(&PasswordStore::AddFieldInfoImpl, this, field_info));
456 }
457
GetAllFieldInfo(PasswordStoreConsumer * consumer)458 void PasswordStore::GetAllFieldInfo(PasswordStoreConsumer* consumer) {
459 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
460 auto get_all_field_info_task =
461 base::BindOnce(&PasswordStore::GetAllFieldInfoImpl, this);
462 consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
463 background_task_runner_.get(), FROM_HERE,
464 std::move(get_all_field_info_task),
465 base::BindOnce(&PasswordStoreConsumer::OnGetAllFieldInfo,
466 consumer->GetWeakPtr()));
467 }
468
RemoveFieldInfoByTime(base::Time remove_begin,base::Time remove_end,base::OnceClosure completion)469 void PasswordStore::RemoveFieldInfoByTime(base::Time remove_begin,
470 base::Time remove_end,
471 base::OnceClosure completion) {
472 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
473 ScheduleTask(base::BindOnce(&PasswordStore::RemoveFieldInfoByTimeInternal,
474 this, remove_begin, remove_end,
475 std::move(completion)));
476 }
477
ClearStore(base::OnceCallback<void (bool)> completion)478 void PasswordStore::ClearStore(base::OnceCallback<void(bool)> completion) {
479 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
480 ScheduleTask(base::BindOnce(&PasswordStore::ClearStoreInternal, this,
481 std::move(completion)));
482 }
483
AddObserver(Observer * observer)484 void PasswordStore::AddObserver(Observer* observer) {
485 observers_->AddObserver(observer);
486 }
487
RemoveObserver(Observer * observer)488 void PasswordStore::RemoveObserver(Observer* observer) {
489 observers_->RemoveObserver(observer);
490 }
491
AddDatabaseCompromisedCredentialsObserver(DatabaseCompromisedCredentialsObserver * observer)492 void PasswordStore::AddDatabaseCompromisedCredentialsObserver(
493 DatabaseCompromisedCredentialsObserver* observer) {
494 compromised_credentials_observers_->AddObserver(observer);
495 }
496
RemoveDatabaseCompromisedCredentialsObserver(DatabaseCompromisedCredentialsObserver * observer)497 void PasswordStore::RemoveDatabaseCompromisedCredentialsObserver(
498 DatabaseCompromisedCredentialsObserver* observer) {
499 compromised_credentials_observers_->RemoveObserver(observer);
500 }
501
ScheduleTask(base::OnceClosure task)502 bool PasswordStore::ScheduleTask(base::OnceClosure task) {
503 return background_task_runner_ &&
504 background_task_runner_->PostTask(FROM_HERE, std::move(task));
505 }
506
IsAbleToSavePasswords() const507 bool PasswordStore::IsAbleToSavePasswords() const {
508 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
509 return init_status_ == InitStatus::kSuccess;
510 }
511
ShutdownOnUIThread()512 void PasswordStore::ShutdownOnUIThread() {
513 ScheduleTask(
514 base::BindOnce(&PasswordStore::DestroyOnBackgroundSequence, this));
515 // The AffiliationService must be destroyed from the main sequence.
516 affiliated_match_helper_.reset();
517 shutdown_called_ = true;
518 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
519 if (notifier_)
520 notifier_->UnsubscribeFromSigninEvents();
521 #endif
522 }
523
524 std::unique_ptr<syncer::ProxyModelTypeControllerDelegate>
CreateSyncControllerDelegate()525 PasswordStore::CreateSyncControllerDelegate() {
526 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
527 // Note that a callback is bound for
528 // GetSyncControllerDelegateOnBackgroundSequence() because this getter itself
529 // must also run in the backend sequence, and the proxy object below will take
530 // care of that.
531 return std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
532 background_task_runner_,
533 base::BindRepeating(
534 &PasswordStore::GetSyncControllerDelegateOnBackgroundSequence,
535 base::Unretained(this)));
536 }
537
SetUnsyncedCredentialsDeletionNotifier(std::unique_ptr<PasswordStore::UnsyncedCredentialsDeletionNotifier> notifier)538 void PasswordStore::SetUnsyncedCredentialsDeletionNotifier(
539 std::unique_ptr<PasswordStore::UnsyncedCredentialsDeletionNotifier>
540 notifier) {
541 DCHECK(!deletion_notifier_);
542 DCHECK(notifier);
543 deletion_notifier_ = std::move(notifier);
544 }
545
SetSyncTaskTimeoutForTest(base::TimeDelta timeout)546 void PasswordStore::SetSyncTaskTimeoutForTest(base::TimeDelta timeout) {
547 sync_task_timeout_ = timeout;
548 }
549
CheckReuse(const base::string16 & input,const std::string & domain,PasswordReuseDetectorConsumer * consumer)550 void PasswordStore::CheckReuse(const base::string16& input,
551 const std::string& domain,
552 PasswordReuseDetectorConsumer* consumer) {
553 ScheduleTask(base::BindOnce(&PasswordStore::CheckReuseImpl, this,
554 std::make_unique<CheckReuseRequest>(consumer),
555 input, domain));
556 }
557
PreparePasswordHashData(const std::string & sync_username,const bool is_signed_in)558 void PasswordStore::PreparePasswordHashData(const std::string& sync_username,
559 const bool is_signed_in) {
560 SchedulePasswordHashUpdate(/*should_log_metrics=*/true,
561 !sync_username.empty(), is_signed_in);
562 ScheduleEnterprisePasswordURLUpdate();
563 }
564
SaveGaiaPasswordHash(const std::string & username,const base::string16 & password,bool is_primary_account,GaiaPasswordHashChange event)565 void PasswordStore::SaveGaiaPasswordHash(const std::string& username,
566 const base::string16& password,
567 bool is_primary_account,
568 GaiaPasswordHashChange event) {
569 SaveProtectedPasswordHash(username, password, is_primary_account,
570 /*is_gaia_password=*/true, event);
571 }
572
SaveEnterprisePasswordHash(const std::string & username,const base::string16 & password)573 void PasswordStore::SaveEnterprisePasswordHash(const std::string& username,
574 const base::string16& password) {
575 SaveProtectedPasswordHash(
576 username, password, /*is_primary_account=*/false,
577 /*is_gaia_password=*/false,
578 GaiaPasswordHashChange::NON_GAIA_ENTERPRISE_PASSWORD_CHANGE);
579 }
580
SaveProtectedPasswordHash(const std::string & username,const base::string16 & password,bool is_primary_account,bool is_gaia_password,GaiaPasswordHashChange event)581 void PasswordStore::SaveProtectedPasswordHash(const std::string& username,
582 const base::string16& password,
583 bool is_primary_account,
584 bool is_gaia_password,
585 GaiaPasswordHashChange event) {
586 if (hash_password_manager_.SavePasswordHash(username, password,
587 is_gaia_password)) {
588 if (is_gaia_password) {
589 metrics_util::LogGaiaPasswordHashChange(event, is_primary_account);
590 }
591 // This method is not being called on startup so it shouldn't log metrics.
592 // |is_signed_in| is only used when |should_log_metrics| is true so
593 // it doesn't matter what the value is here.
594 SchedulePasswordHashUpdate(/*should_log_metrics=*/false, is_primary_account,
595 /*is_signed_in=*/false);
596 }
597 }
598
SaveSyncPasswordHash(const PasswordHashData & sync_password_data,GaiaPasswordHashChange event)599 void PasswordStore::SaveSyncPasswordHash(
600 const PasswordHashData& sync_password_data,
601 GaiaPasswordHashChange event) {
602 if (hash_password_manager_.SavePasswordHash(sync_password_data)) {
603 metrics_util::LogGaiaPasswordHashChange(event,
604 /*is_sync_password=*/true);
605 SchedulePasswordHashUpdate(/*should_log_metrics=*/false,
606 /*does_primary_account_exists=*/false,
607 /*is_signed_in=*/false);
608 }
609 }
610
ClearGaiaPasswordHash(const std::string & username)611 void PasswordStore::ClearGaiaPasswordHash(const std::string& username) {
612 hash_password_manager_.ClearSavedPasswordHash(username,
613 /*is_gaia_password=*/true);
614 ScheduleTask(base::BindOnce(&PasswordStore::ClearGaiaPasswordHashImpl, this,
615 username));
616 }
617
ClearAllGaiaPasswordHash()618 void PasswordStore::ClearAllGaiaPasswordHash() {
619 hash_password_manager_.ClearAllPasswordHash(/* is_gaia_password= */ true);
620 ScheduleTask(
621 base::BindOnce(&PasswordStore::ClearAllGaiaPasswordHashImpl, this));
622 }
623
ClearAllEnterprisePasswordHash()624 void PasswordStore::ClearAllEnterprisePasswordHash() {
625 hash_password_manager_.ClearAllPasswordHash(/* is_gaia_password= */ false);
626 ScheduleTask(
627 base::BindOnce(&PasswordStore::ClearAllEnterprisePasswordHashImpl, this));
628 }
629
ClearAllNonGmailPasswordHash()630 void PasswordStore::ClearAllNonGmailPasswordHash() {
631 hash_password_manager_.ClearAllNonGmailPasswordHash();
632 ScheduleTask(
633 base::BindOnce(&PasswordStore::ClearAllNonGmailPasswordHashImpl, this));
634 }
635
636 std::unique_ptr<StateSubscription>
RegisterStateCallbackOnHashPasswordManager(const base::RepeatingCallback<void (const std::string & username)> & callback)637 PasswordStore::RegisterStateCallbackOnHashPasswordManager(
638 const base::RepeatingCallback<void(const std::string& username)>&
639 callback) {
640 return hash_password_manager_.RegisterStateCallback(callback);
641 }
642
SetPasswordStoreSigninNotifier(std::unique_ptr<PasswordStoreSigninNotifier> notifier)643 void PasswordStore::SetPasswordStoreSigninNotifier(
644 std::unique_ptr<PasswordStoreSigninNotifier> notifier) {
645 DCHECK(!notifier_);
646 DCHECK(notifier);
647 notifier_ = std::move(notifier);
648 notifier_->SubscribeToSigninEvents(this);
649 }
650
SchedulePasswordHashUpdate(bool should_log_metrics,bool does_primary_account_exists,bool is_signed_in)651 void PasswordStore::SchedulePasswordHashUpdate(bool should_log_metrics,
652 bool does_primary_account_exists,
653 bool is_signed_in) {
654 ScheduleTask(base::BindOnce(
655 &PasswordStore::SaveProtectedPasswordHashImpl, this,
656 hash_password_manager_.RetrieveAllPasswordHashes(), should_log_metrics,
657 does_primary_account_exists, is_signed_in));
658 }
659
ScheduleEnterprisePasswordURLUpdate()660 void PasswordStore::ScheduleEnterprisePasswordURLUpdate() {
661 std::vector<GURL> enterprise_login_urls;
662 safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs_,
663 &enterprise_login_urls);
664 GURL enterprise_change_password_url =
665 safe_browsing::GetPasswordProtectionChangePasswordURLPref(*prefs_);
666
667 ScheduleTask(base::BindOnce(&PasswordStore::SaveEnterprisePasswordURLs, this,
668 std::move(enterprise_login_urls),
669 std::move(enterprise_change_password_url)));
670 }
671
~PasswordStore()672 PasswordStore::~PasswordStore() {
673 DCHECK(shutdown_called_);
674 // PasswordSyncBridge should delete on the same sequence where it was created.
675 if (sync_bridge_)
676 background_task_runner_->DeleteSoon(FROM_HERE, std::move(sync_bridge_));
677 }
678
679 scoped_refptr<base::SequencedTaskRunner>
CreateBackgroundTaskRunner() const680 PasswordStore::CreateBackgroundTaskRunner() const {
681 return base::ThreadPool::CreateSequencedTaskRunner(
682 {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
683 }
684
InitOnBackgroundSequence()685 bool PasswordStore::InitOnBackgroundSequence() {
686 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
687 sync_bridge_ = base::WrapUnique(new PasswordSyncBridge(
688 std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
689 syncer::PASSWORDS, base::DoNothing()),
690 /*password_store_sync=*/this, sync_enabled_or_disabled_cb_));
691
692 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
693 reuse_detector_ = new PasswordReuseDetector;
694
695 base::SequencedTaskRunnerHandle::Get()->PostTask(
696 FROM_HERE,
697 base::BindOnce(&PasswordStoreConsumer::OnGetPasswordStoreResultsFrom,
698 reuse_detector_->GetWeakPtr(), base::RetainedRef(this),
699 GetAutofillableLoginsImpl()));
700 #endif
701 return true;
702 }
703
AddLoginSync(const PasswordForm & form,AddLoginError * error)704 PasswordStoreChangeList PasswordStore::AddLoginSync(const PasswordForm& form,
705 AddLoginError* error) {
706 // There is no good way to check if the password is actually up to date, or
707 // at least to check if it was actually changed. Assume it is.
708 if (AffiliatedMatchHelper::IsValidAndroidCredential(
709 PasswordStore::FormDigest(form)))
710 ScheduleFindAndUpdateAffiliatedWebLogins(form);
711 return AddLoginImpl(form, error);
712 }
713
UpdateLoginSync(const PasswordForm & form,UpdateLoginError * error)714 PasswordStoreChangeList PasswordStore::UpdateLoginSync(
715 const PasswordForm& form,
716 UpdateLoginError* error) {
717 if (AffiliatedMatchHelper::IsValidAndroidCredential(
718 PasswordStore::FormDigest(form))) {
719 // Ideally, a |form| would not be updated in any way unless it was ensured
720 // that it, as a whole, can be used for a successful login. This, sadly, can
721 // not be guaranteed. It might be that |form| just contains updates to some
722 // meta-attribute, while it still has an out-of-date password. If such a
723 // password were to be propagated to affiliated credentials in that case, it
724 // may very well overwrite the actual, up-to-date password. Try to mitigate
725 // this risk by ignoring updates unless they actually update the password.
726 std::unique_ptr<PasswordForm> old_form(GetLoginImpl(form));
727 if (old_form && form.password_value != old_form->password_value)
728 ScheduleFindAndUpdateAffiliatedWebLogins(form);
729 }
730 return UpdateLoginImpl(form, error);
731 }
732
RemoveLoginSync(const PasswordForm & form)733 PasswordStoreChangeList PasswordStore::RemoveLoginSync(
734 const PasswordForm& form) {
735 return RemoveLoginImpl(form);
736 }
737
NotifyLoginsChanged(const PasswordStoreChangeList & changes)738 void PasswordStore::NotifyLoginsChanged(
739 const PasswordStoreChangeList& changes) {
740 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
741 if (!changes.empty()) {
742 observers_->Notify(FROM_HERE, &Observer::OnLoginsChangedIn,
743 base::RetainedRef(this), changes);
744 if (sync_bridge_)
745 sync_bridge_->ActOnPasswordStoreChanges(changes);
746
747 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
748 if (reuse_detector_)
749 reuse_detector_->OnLoginsChanged(changes);
750 #endif
751 ProcessLoginsChanged(
752 changes,
753 base::BindRepeating(
754 [](scoped_refptr<PasswordStore> store,
755 const std::string& signon_realm, const base::string16& username,
756 RemoveCompromisedCredentialsReason reason) {
757 auto callback = base::BindOnce(
758 &PasswordStore::RemoveCompromisedCredentialsImpl, store,
759 signon_realm, username, reason);
760 store->InvokeAndNotifyAboutCompromisedPasswordsChange(
761 std::move(callback));
762 },
763 scoped_refptr<PasswordStore>(this)));
764 }
765 }
766
NotifyDeletionsHaveSynced(bool success)767 void PasswordStore::NotifyDeletionsHaveSynced(bool success) {
768 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
769 // Either all deletions have been committed to the Sync server, or Sync is
770 // telling us that it won't commit them (because Sync was turned off
771 // permanently). In either case, run the corresponding callbacks now (on the
772 // main task runner).
773 DCHECK(!success || !GetMetadataStore()->HasUnsyncedDeletions());
774 if (!deletions_have_synced_callbacks_.empty()) {
775 base::UmaHistogramBoolean(
776 "PasswordManager.PasswordStoreDeletionsHaveSynced", success);
777 }
778 for (auto& callback : deletions_have_synced_callbacks_) {
779 main_task_runner_->PostTask(FROM_HERE,
780 base::BindOnce(std::move(callback), success));
781 }
782 deletions_have_synced_timeout_.Cancel();
783 deletions_have_synced_callbacks_.clear();
784 }
785
InvokeAndNotifyAboutCompromisedPasswordsChange(base::OnceCallback<bool ()> callback)786 void PasswordStore::InvokeAndNotifyAboutCompromisedPasswordsChange(
787 base::OnceCallback<bool()> callback) {
788 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
789 if (std::move(callback).Run()) {
790 compromised_credentials_observers_->Notify(
791 FROM_HERE,
792 &DatabaseCompromisedCredentialsObserver::
793 OnCompromisedCredentialsChangedIn,
794 base::RetainedRef(this));
795 }
796 }
797
NotifyUnsyncedCredentialsWillBeDeleted(std::vector<PasswordForm> unsynced_credentials)798 void PasswordStore::NotifyUnsyncedCredentialsWillBeDeleted(
799 std::vector<PasswordForm> unsynced_credentials) {
800 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
801 DCHECK(IsAccountStore());
802 // |deletion_notifier_| only gets set for desktop.
803 if (deletion_notifier_) {
804 main_task_runner_->PostTask(
805 FROM_HERE,
806 base::BindOnce(
807 &PasswordStore::UnsyncedCredentialsDeletionNotifier::Notify,
808 deletion_notifier_->GetWeakPtr(), std::move(unsynced_credentials)));
809 }
810 }
811
CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,const base::string16 & input,const std::string & domain)812 void PasswordStore::CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,
813 const base::string16& input,
814 const std::string& domain) {
815 if (reuse_detector_) {
816 reuse_detector_->CheckReuse(input, domain, request.get());
817 } else {
818 request->OnReuseCheckDone(false, 0, base::nullopt, {}, 0);
819 }
820 }
821
SaveProtectedPasswordHashImpl(PasswordHashDataList protected_password_data_list,bool should_log_metrics,bool does_primary_account_exists,bool is_signed_in)822 void PasswordStore::SaveProtectedPasswordHashImpl(
823 PasswordHashDataList protected_password_data_list,
824 bool should_log_metrics,
825 bool does_primary_account_exists,
826 bool is_signed_in) {
827 if (!reuse_detector_ || !protected_password_data_list.has_value())
828 return;
829 TRACE_EVENT0("passwords", "PasswordStore::SaveProtectedPasswordHashImpl");
830
831 std::vector<PasswordHashData> gaia_password_hash_list;
832 std::vector<PasswordHashData> enterprise_password_hash_list;
833 for (PasswordHashData& password_hash : *protected_password_data_list) {
834 if (password_hash.is_gaia_password)
835 gaia_password_hash_list.push_back(std::move(password_hash));
836 else
837 enterprise_password_hash_list.push_back(std::move(password_hash));
838 }
839
840 if (should_log_metrics) {
841 metrics_util::LogProtectedPasswordHashCounts(
842 gaia_password_hash_list.size(), enterprise_password_hash_list.size(),
843 does_primary_account_exists, is_signed_in);
844 }
845 reuse_detector_->UseGaiaPasswordHash(std::move(gaia_password_hash_list));
846 reuse_detector_->UseNonGaiaEnterprisePasswordHash(
847 std::move(enterprise_password_hash_list));
848 }
849
SaveEnterprisePasswordURLs(const std::vector<GURL> & enterprise_login_urls,const GURL & enterprise_change_password_url)850 void PasswordStore::SaveEnterprisePasswordURLs(
851 const std::vector<GURL>& enterprise_login_urls,
852 const GURL& enterprise_change_password_url) {
853 if (!reuse_detector_)
854 return;
855 TRACE_EVENT0("passwords", "PasswordStore::SaveEnterprisePasswordURLs");
856 reuse_detector_->UseEnterprisePasswordURLs(std::move(enterprise_login_urls),
857 enterprise_change_password_url);
858 }
859
ClearGaiaPasswordHashImpl(const std::string & username)860 void PasswordStore::ClearGaiaPasswordHashImpl(const std::string& username) {
861 TRACE_EVENT0("passwords", "PasswordStore::ClearGaiaPasswordHashImpl");
862 if (reuse_detector_)
863 reuse_detector_->ClearGaiaPasswordHash(username);
864 }
865
ClearAllGaiaPasswordHashImpl()866 void PasswordStore::ClearAllGaiaPasswordHashImpl() {
867 TRACE_EVENT0("passwords", "PasswordStore::ClearAllGaiaPasswordHashImpl");
868 if (reuse_detector_)
869 reuse_detector_->ClearAllGaiaPasswordHash();
870 }
871
ClearAllEnterprisePasswordHashImpl()872 void PasswordStore::ClearAllEnterprisePasswordHashImpl() {
873 TRACE_EVENT0("passwords",
874 "PasswordStore::ClearAllEnterprisePasswordHashImpl");
875 if (reuse_detector_)
876 reuse_detector_->ClearAllEnterprisePasswordHash();
877 }
878
ClearAllNonGmailPasswordHashImpl()879 void PasswordStore::ClearAllNonGmailPasswordHashImpl() {
880 TRACE_EVENT0("passwords", "PasswordStore::ClearAllNonGmailPasswordHashImpl");
881 if (reuse_detector_)
882 reuse_detector_->ClearAllNonGmailPasswordHash();
883 }
884
OnInitCompleted(bool success)885 void PasswordStore::OnInitCompleted(bool success) {
886 DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
887 init_status_ = success ? InitStatus::kSuccess : InitStatus::kFailure;
888
889 UMA_HISTOGRAM_BOOLEAN("PasswordManager.PasswordStoreInitResult", success);
890 TRACE_EVENT_NESTABLE_ASYNC_END0(
891 "passwords", "PasswordStore::InitOnBackgroundSequence", this);
892 }
893
PostLoginsTaskAndReplyToConsumerWithResult(PasswordStoreConsumer * consumer,LoginsTask task)894 void PasswordStore::PostLoginsTaskAndReplyToConsumerWithResult(
895 PasswordStoreConsumer* consumer,
896 LoginsTask task) {
897 consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
898 background_task_runner_.get(), FROM_HERE, std::move(task),
899 base::BindOnce(&PasswordStoreConsumer::OnGetPasswordStoreResultsFrom,
900 consumer->GetWeakPtr(), base::RetainedRef(this)));
901 }
902
PostLoginsTaskAndReplyToConsumerWithProcessedResult(const char * trace_name,PasswordStoreConsumer * consumer,LoginsTask task,LoginsResultProcessor processor)903 void PasswordStore::PostLoginsTaskAndReplyToConsumerWithProcessedResult(
904 const char* trace_name,
905 PasswordStoreConsumer* consumer,
906 LoginsTask task,
907 LoginsResultProcessor processor) {
908 auto call_consumer = base::BindOnce(
909 CloseTraceAndCallBack, trace_name, consumer,
910 base::BindOnce(&PasswordStoreConsumer::OnGetPasswordStoreResultsFrom,
911 consumer->GetWeakPtr(), base::RetainedRef(this)));
912 consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
913 background_task_runner_.get(), FROM_HERE, std::move(task),
914 base::BindOnce(std::move(processor), std::move(call_consumer)));
915 }
916
PostStatsTaskAndReplyToConsumerWithResult(PasswordStoreConsumer * consumer,StatsTask task)917 void PasswordStore::PostStatsTaskAndReplyToConsumerWithResult(
918 PasswordStoreConsumer* consumer,
919 StatsTask task) {
920 consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
921 background_task_runner_.get(), FROM_HERE, std::move(task),
922 base::BindOnce(&PasswordStoreConsumer::OnGetSiteStatistics,
923 consumer->GetWeakPtr()));
924 }
925
PostCompromisedCredentialsTaskAndReplyToConsumerWithResult(CompromisedCredentialsConsumer * consumer,CompromisedCredentialsTask task)926 void PasswordStore::PostCompromisedCredentialsTaskAndReplyToConsumerWithResult(
927 CompromisedCredentialsConsumer* consumer,
928 CompromisedCredentialsTask task) {
929 consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
930 background_task_runner_.get(), FROM_HERE, std::move(task),
931 base::BindOnce(
932 &CompromisedCredentialsConsumer::OnGetCompromisedCredentialsFrom,
933 consumer->GetWeakPtr(), base::RetainedRef(this)));
934 }
935
AddLoginInternal(const PasswordForm & form)936 void PasswordStore::AddLoginInternal(const PasswordForm& form) {
937 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
938 TRACE_EVENT0("passwords", "PasswordStore::AddLoginInternal");
939 BeginTransaction();
940 PasswordStoreChangeList changes = AddLoginImpl(form);
941 NotifyLoginsChanged(changes);
942 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
943 // CommitTransaction() must be called after NotifyLoginsChanged(), because
944 // sync codebase needs to update metadata atomically together with the login
945 // data.
946 CommitTransaction();
947 }
948
UpdateLoginInternal(const PasswordForm & form)949 void PasswordStore::UpdateLoginInternal(const PasswordForm& form) {
950 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
951 TRACE_EVENT0("passwords", "PasswordStore::UpdateLoginInternal");
952 BeginTransaction();
953 PasswordStoreChangeList changes = UpdateLoginImpl(form);
954 NotifyLoginsChanged(changes);
955 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
956 // CommitTransaction() must be called after NotifyLoginsChanged(), because
957 // sync codebase needs to update metadata atomically together with the login
958 // data.
959 CommitTransaction();
960 }
961
RemoveLoginInternal(const PasswordForm & form)962 void PasswordStore::RemoveLoginInternal(const PasswordForm& form) {
963 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
964 TRACE_EVENT0("passwords", "PasswordStore::RemoveLoginInternal");
965 BeginTransaction();
966 PasswordStoreChangeList changes = RemoveLoginImpl(form);
967 NotifyLoginsChanged(changes);
968 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
969 // CommitTransaction() must be called after NotifyLoginsChanged(), because
970 // sync codebase needs to update metadata atomically together with the login
971 // data.
972 CommitTransaction();
973 }
974
UpdateLoginWithPrimaryKeyInternal(const PasswordForm & new_form,const PasswordForm & old_primary_key)975 void PasswordStore::UpdateLoginWithPrimaryKeyInternal(
976 const PasswordForm& new_form,
977 const PasswordForm& old_primary_key) {
978 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
979 TRACE_EVENT0("passwords", "PasswordStore::UpdateLoginWithPrimaryKeyInternal");
980 BeginTransaction();
981 PasswordStoreChangeList all_changes = RemoveLoginImpl(old_primary_key);
982 PasswordStoreChangeList changes = AddLoginImpl(new_form);
983 all_changes.insert(all_changes.end(), changes.begin(), changes.end());
984 NotifyLoginsChanged(all_changes);
985 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
986 // CommitTransaction() must be called after NotifyLoginsChanged(), because
987 // sync codebase needs to update metadata atomically together with the login
988 // data.
989 CommitTransaction();
990 }
991
RemoveLoginsByURLAndTimeInternal(const base::RepeatingCallback<bool (const GURL &)> & url_filter,base::Time delete_begin,base::Time delete_end,base::OnceClosure completion,base::OnceCallback<void (bool)> sync_completion)992 void PasswordStore::RemoveLoginsByURLAndTimeInternal(
993 const base::RepeatingCallback<bool(const GURL&)>& url_filter,
994 base::Time delete_begin,
995 base::Time delete_end,
996 base::OnceClosure completion,
997 base::OnceCallback<void(bool)> sync_completion) {
998 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
999 TRACE_EVENT0("passwords", "PasswordStore::RemoveLoginsByURLAndTimeInternal");
1000 BeginTransaction();
1001 PasswordStoreChangeList changes =
1002 RemoveLoginsByURLAndTimeImpl(url_filter, delete_begin, delete_end);
1003 NotifyLoginsChanged(changes);
1004 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
1005 // CommitTransaction() must be called after NotifyLoginsChanged(), because
1006 // sync codebase needs to update metadata atomically together with the login
1007 // data.
1008 CommitTransaction();
1009
1010 if (completion)
1011 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1012
1013 if (sync_completion) {
1014 deletions_have_synced_callbacks_.push_back(std::move(sync_completion));
1015 // Start a timeout for sync, or restart it if it was already running.
1016 deletions_have_synced_timeout_.Reset(base::BindRepeating(
1017 &PasswordStore::NotifyDeletionsHaveSynced, this, /*success=*/false));
1018 background_task_runner_->PostDelayedTask(
1019 FROM_HERE, deletions_have_synced_timeout_.callback(),
1020 sync_task_timeout_);
1021
1022 // Do an immediate check for the case where there are already no unsynced
1023 // deletions.
1024 if (!GetMetadataStore()->HasUnsyncedDeletions())
1025 NotifyDeletionsHaveSynced(/*success=*/true);
1026 }
1027 }
1028
RemoveLoginsCreatedBetweenInternal(base::Time delete_begin,base::Time delete_end,base::OnceClosure completion)1029 void PasswordStore::RemoveLoginsCreatedBetweenInternal(
1030 base::Time delete_begin,
1031 base::Time delete_end,
1032 base::OnceClosure completion) {
1033 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1034 TRACE_EVENT0("passwords",
1035 "PasswordStore::RemoveLoginsCreatedBetweenInternal");
1036 BeginTransaction();
1037 PasswordStoreChangeList changes =
1038 RemoveLoginsCreatedBetweenImpl(delete_begin, delete_end);
1039 NotifyLoginsChanged(changes);
1040 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
1041 // CommitTransaction() must be called after NotifyLoginsChanged(), because
1042 // sync codebase needs to update metadata atomically together with the login
1043 // data.
1044 CommitTransaction();
1045 if (completion)
1046 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1047 }
1048
RemoveStatisticsByOriginAndTimeInternal(const base::RepeatingCallback<bool (const GURL &)> & origin_filter,base::Time delete_begin,base::Time delete_end,base::OnceClosure completion)1049 void PasswordStore::RemoveStatisticsByOriginAndTimeInternal(
1050 const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
1051 base::Time delete_begin,
1052 base::Time delete_end,
1053 base::OnceClosure completion) {
1054 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1055 TRACE_EVENT0("passwords",
1056 "PasswordStore::RemoveStatisticsByOriginAndTimeInternal");
1057 RemoveStatisticsByOriginAndTimeImpl(origin_filter, delete_begin, delete_end);
1058 if (completion)
1059 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1060 }
1061
DisableAutoSignInForOriginsInternal(const base::RepeatingCallback<bool (const GURL &)> & origin_filter,base::OnceClosure completion)1062 void PasswordStore::DisableAutoSignInForOriginsInternal(
1063 const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
1064 base::OnceClosure completion) {
1065 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1066 TRACE_EVENT0("passwords",
1067 "PasswordStore::DisableAutoSignInForOriginsInternal");
1068 DisableAutoSignInForOriginsImpl(origin_filter);
1069 if (completion)
1070 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1071 }
1072
UnblacklistInternal(const PasswordStore::FormDigest & form_digest,base::OnceClosure completion)1073 void PasswordStore::UnblacklistInternal(
1074 const PasswordStore::FormDigest& form_digest,
1075 base::OnceClosure completion) {
1076 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1077 TRACE_EVENT0("passwords", "PasswordStore::UnblacklistInternal");
1078
1079 std::vector<std::unique_ptr<PasswordForm>> all_matches =
1080 GetLoginsImpl(form_digest);
1081 for (auto& form : all_matches) {
1082 // Ignore PSL matches for blocked entries.
1083 if (form->blocked_by_user && !form->is_public_suffix_match)
1084 RemoveLoginInternal(*form);
1085 }
1086 if (completion)
1087 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1088 }
1089
RemoveCompromisedCredentialsByUrlAndTimeInternal(const base::RepeatingCallback<bool (const GURL &)> & url_filter,base::Time remove_begin,base::Time remove_end,base::OnceClosure completion)1090 bool PasswordStore::RemoveCompromisedCredentialsByUrlAndTimeInternal(
1091 const base::RepeatingCallback<bool(const GURL&)>& url_filter,
1092 base::Time remove_begin,
1093 base::Time remove_end,
1094 base::OnceClosure completion) {
1095 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1096 bool result = RemoveCompromisedCredentialsByUrlAndTimeImpl(
1097 url_filter, remove_begin, remove_end);
1098 if (completion)
1099 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1100 return result;
1101 }
1102
RemoveFieldInfoByTimeInternal(base::Time remove_begin,base::Time remove_end,base::OnceClosure completion)1103 void PasswordStore::RemoveFieldInfoByTimeInternal(
1104 base::Time remove_begin,
1105 base::Time remove_end,
1106 base::OnceClosure completion) {
1107 RemoveFieldInfoByTimeImpl(remove_begin, remove_end);
1108 if (completion)
1109 main_task_runner_->PostTask(FROM_HERE, std::move(completion));
1110 }
1111
ClearStoreInternal(base::OnceCallback<void (bool)> completion)1112 void PasswordStore::ClearStoreInternal(
1113 base::OnceCallback<void(bool)> completion) {
1114 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1115 bool should_clear = !IsEmpty();
1116 if (should_clear)
1117 DeleteAndRecreateDatabaseFile();
1118 if (completion) {
1119 main_task_runner_->PostTask(
1120 FROM_HERE, base::BindOnce(std::move(completion), should_clear));
1121 }
1122 }
1123
GetLoginsImpl(const FormDigest & form)1124 std::vector<std::unique_ptr<PasswordForm>> PasswordStore::GetLoginsImpl(
1125 const FormDigest& form) {
1126 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1127 return FillMatchingLogins(form);
1128 }
1129
1130 std::vector<std::unique_ptr<PasswordForm>>
GetLoginsByPasswordImpl(const base::string16 & plain_text_password)1131 PasswordStore::GetLoginsByPasswordImpl(
1132 const base::string16& plain_text_password) {
1133 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1134 TRACE_EVENT0("passwords", "PasswordStore::GetLoginsByPasswordImpl");
1135 return FillMatchingLoginsByPassword(plain_text_password);
1136 }
1137
1138 std::vector<std::unique_ptr<PasswordForm>>
GetAutofillableLoginsImpl()1139 PasswordStore::GetAutofillableLoginsImpl() {
1140 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1141 TRACE_EVENT0("passwords", "PasswordStore::GetAutofillableLoginsImpl");
1142 std::vector<std::unique_ptr<PasswordForm>> obtained_forms;
1143 if (!FillAutofillableLogins(&obtained_forms))
1144 obtained_forms.clear();
1145 return obtained_forms;
1146 }
1147
GetAllLoginsImpl()1148 std::vector<std::unique_ptr<PasswordForm>> PasswordStore::GetAllLoginsImpl() {
1149 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1150 TRACE_EVENT0("passwords", "PasswordStore::GetAllLoginsImpl");
1151 std::vector<std::unique_ptr<PasswordForm>> results;
1152 for (auto fill_logins : {&PasswordStore::FillAutofillableLogins,
1153 &PasswordStore::FillBlacklistLogins}) {
1154 std::vector<std::unique_ptr<PasswordForm>> obtained_forms;
1155 if ((this->*fill_logins)(&obtained_forms)) {
1156 results.insert(results.end(),
1157 std::make_move_iterator(obtained_forms.begin()),
1158 std::make_move_iterator(obtained_forms.end()));
1159 }
1160 }
1161
1162 return results;
1163 }
1164
1165 std::vector<std::unique_ptr<PasswordForm>>
GetLoginsWithAffiliationsImpl(const FormDigest & form,const std::vector<std::string> & additional_android_realms)1166 PasswordStore::GetLoginsWithAffiliationsImpl(
1167 const FormDigest& form,
1168 const std::vector<std::string>& additional_android_realms) {
1169 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1170 std::vector<std::unique_ptr<PasswordForm>> results(FillMatchingLogins(form));
1171 for (const std::string& realm : additional_android_realms) {
1172 std::vector<std::unique_ptr<PasswordForm>> more_results(
1173 FillMatchingLogins({PasswordForm::Scheme::kHtml, realm, GURL()}));
1174 for (auto& result : more_results)
1175 result->is_affiliation_based_match = true;
1176 password_manager_util::TrimUsernameOnlyCredentials(&more_results);
1177 results.insert(results.end(), std::make_move_iterator(more_results.begin()),
1178 std::make_move_iterator(more_results.end()));
1179 }
1180
1181 return results;
1182 }
1183
1184 std::vector<CompromisedCredentials>
GetCompromisedWithAffiliationsImpl(const std::string & signon_realm,const std::vector<std::string> & additional_android_realms)1185 PasswordStore::GetCompromisedWithAffiliationsImpl(
1186 const std::string& signon_realm,
1187 const std::vector<std::string>& additional_android_realms) {
1188 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1189 std::vector<CompromisedCredentials> results(
1190 GetMatchingCompromisedCredentialsImpl(signon_realm));
1191 for (const std::string& realm : additional_android_realms) {
1192 std::vector<CompromisedCredentials> more_results(
1193 GetMatchingCompromisedCredentialsImpl(realm));
1194 results.insert(results.end(), std::make_move_iterator(more_results.begin()),
1195 std::make_move_iterator(more_results.end()));
1196 }
1197
1198 return results;
1199 }
1200
InjectAffiliationAndBrandingInformation(LoginsReply callback,LoginsResult forms)1201 void PasswordStore::InjectAffiliationAndBrandingInformation(
1202 LoginsReply callback,
1203 LoginsResult forms) {
1204 if (affiliated_match_helper_) {
1205 affiliated_match_helper_->InjectAffiliationAndBrandingInformation(
1206 std::move(forms), AndroidAffiliationService::StrategyOnCacheMiss::FAIL,
1207 std::move(callback));
1208 } else {
1209 std::move(callback).Run(std::move(forms));
1210 }
1211 }
1212
ScheduleGetFilteredLoginsWithAffiliations(base::WeakPtr<PasswordStoreConsumer> consumer,const PasswordStore::FormDigest & form,base::Time cutoff,const std::vector<std::string> & additional_android_realms)1213 void PasswordStore::ScheduleGetFilteredLoginsWithAffiliations(
1214 base::WeakPtr<PasswordStoreConsumer> consumer,
1215 const PasswordStore::FormDigest& form,
1216 base::Time cutoff,
1217 const std::vector<std::string>& additional_android_realms) {
1218 if (consumer) {
1219 PostLoginsTaskAndReplyToConsumerWithProcessedResult(
1220 "PasswordStore::GetLogins", consumer.get(),
1221 base::BindOnce(&PasswordStore::GetLoginsWithAffiliationsImpl, this,
1222 form, additional_android_realms),
1223 base::BindOnce(FilterLogins, cutoff));
1224 }
1225 }
1226
ScheduleGetCompromisedWithAffiliations(base::WeakPtr<CompromisedCredentialsConsumer> consumer,const std::string & signon_realm,const std::vector<std::string> & additional_android_realms)1227 void PasswordStore::ScheduleGetCompromisedWithAffiliations(
1228 base::WeakPtr<CompromisedCredentialsConsumer> consumer,
1229 const std::string& signon_realm,
1230 const std::vector<std::string>& additional_android_realms) {
1231 if (consumer) {
1232 PostCompromisedCredentialsTaskAndReplyToConsumerWithResult(
1233 consumer.get(),
1234 base::BindOnce(&PasswordStore::GetCompromisedWithAffiliationsImpl, this,
1235 signon_realm, additional_android_realms));
1236 }
1237 }
1238
GetLoginImpl(const PasswordForm & primary_key)1239 std::unique_ptr<PasswordForm> PasswordStore::GetLoginImpl(
1240 const PasswordForm& primary_key) {
1241 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1242 std::vector<std::unique_ptr<PasswordForm>> candidates(
1243 FillMatchingLogins(FormDigest(primary_key)));
1244 for (auto& candidate : candidates) {
1245 if (ArePasswordFormUniqueKeysEqual(*candidate, primary_key) &&
1246 !candidate->is_public_suffix_match) {
1247 return std::move(candidate);
1248 }
1249 }
1250 return nullptr;
1251 }
1252
FindAndUpdateAffiliatedWebLogins(const PasswordForm & added_or_updated_android_form)1253 void PasswordStore::FindAndUpdateAffiliatedWebLogins(
1254 const PasswordForm& added_or_updated_android_form) {
1255 if (!affiliated_match_helper_)
1256 return;
1257 affiliated_match_helper_->GetAffiliatedWebRealms(
1258 PasswordStore::FormDigest(added_or_updated_android_form),
1259 base::BindOnce(&PasswordStore::ScheduleUpdateAffiliatedWebLoginsImpl,
1260 this, added_or_updated_android_form));
1261 }
1262
ScheduleFindAndUpdateAffiliatedWebLogins(const PasswordForm & added_or_updated_android_form)1263 void PasswordStore::ScheduleFindAndUpdateAffiliatedWebLogins(
1264 const PasswordForm& added_or_updated_android_form) {
1265 main_task_runner_->PostTask(
1266 FROM_HERE,
1267 base::BindOnce(&PasswordStore::FindAndUpdateAffiliatedWebLogins, this,
1268 added_or_updated_android_form));
1269 }
1270
UpdateAffiliatedWebLoginsImpl(const PasswordForm & updated_android_form,const std::vector<std::string> & affiliated_web_realms)1271 void PasswordStore::UpdateAffiliatedWebLoginsImpl(
1272 const PasswordForm& updated_android_form,
1273 const std::vector<std::string>& affiliated_web_realms) {
1274 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1275 BeginTransaction();
1276 PasswordStoreChangeList all_changes;
1277 for (const std::string& affiliated_web_realm : affiliated_web_realms) {
1278 std::vector<std::unique_ptr<PasswordForm>> web_logins(FillMatchingLogins(
1279 {PasswordForm::Scheme::kHtml, affiliated_web_realm, GURL()}));
1280 for (auto& web_login : web_logins) {
1281 // Do not update HTTP logins, logins saved under insecure conditions, and
1282 // non-HTML login forms; PSL matches; logins with a different username;
1283 // and logins with the same password (to avoid generating no-op updates).
1284 if (!AffiliatedMatchHelper::IsValidWebCredential(
1285 FormDigest(*web_login)) ||
1286 web_login->is_public_suffix_match ||
1287 web_login->username_value != updated_android_form.username_value ||
1288 web_login->password_value == updated_android_form.password_value)
1289 continue;
1290
1291 // If the |web_login| was updated in the same or a later chunk of Sync
1292 // changes, assume that it is more recent and do not update it. Note that
1293 // this check is far from perfect conflict resolution and mostly prevents
1294 // long-dormant Sync clients doing damage when they wake up in the face
1295 // of the following list of changes:
1296 //
1297 // Time Source Change
1298 // ==== ====== ======
1299 // #1 Android android_login.password_value = "A"
1300 // #2 Client A web_login.password_value = "A" (propagation)
1301 // #3 Client A web_login.password_value = "B" (manual overwrite)
1302 //
1303 // When long-dormant Sync client B wakes up, it will only get a distilled
1304 // subset of not-yet-obsoleted changes {1, 3}. In this case, client B must
1305 // not propagate password "A" to |web_login|. This is prevented as change
1306 // #3 will arrive either in the same/later chunk of sync changes, so the
1307 // |date_synced| of |web_login| value will be greater or equal.
1308 //
1309 // Note that this solution has several shortcomings:
1310 //
1311 // (1) It will not prevent local changes to |web_login| from being
1312 // overwritten if they were made shortly after start-up, before
1313 // Sync changes are applied. This should be tolerable.
1314 //
1315 // (2) It assumes that all Sync clients are fully capable of propagating
1316 // changes to web credentials on their own. If client C runs an
1317 // older version of Chrome and updates the password for |web_login|
1318 // around the time when the |android_login| is updated, the updated
1319 // password will not be propagated by client B to |web_login| when
1320 // it wakes up, regardless of the temporal order of the original
1321 // changes, as client B will see both credentials having the same
1322 // |data_synced|.
1323 //
1324 // (2a) Above could be mitigated by looking not only at |data_synced|,
1325 // but also at the actual order of Sync changes.
1326 //
1327 // (2b) However, (2a) is still not workable, as a Sync change is made
1328 // when any attribute of the credential is updated, not only the
1329 // password. Hence it is not possible for client B to distinguish
1330 // between two following two event orders:
1331 //
1332 // #1 Android android_login.password_value = "A"
1333 // #2 Client C web_login.password_value = "B" (manual overwrite)
1334 // #3 Android android_login.random_attribute = "..."
1335 //
1336 // #1 Client C web_login.password_value = "B" (manual overwrite)
1337 // #2 Android android_login.password_value = "A"
1338 //
1339 // And so it must assume that it is unsafe to update |web_login|.
1340 if (web_login->date_synced >= updated_android_form.date_synced)
1341 continue;
1342
1343 web_login->password_value = updated_android_form.password_value;
1344
1345 PasswordStoreChangeList changes = UpdateLoginImpl(*web_login);
1346 all_changes.insert(all_changes.end(), changes.begin(), changes.end());
1347 }
1348 }
1349 NotifyLoginsChanged(all_changes);
1350 // Sync metadata get updated in NotifyLoginsChanged(). Therefore,
1351 // CommitTransaction() must be called after NotifyLoginsChanged(), because
1352 // sync codebase needs to update metadata atomically together with the login
1353 // data.
1354 CommitTransaction();
1355 }
1356
ScheduleUpdateAffiliatedWebLoginsImpl(const PasswordForm & updated_android_form,const std::vector<std::string> & affiliated_web_realms)1357 void PasswordStore::ScheduleUpdateAffiliatedWebLoginsImpl(
1358 const PasswordForm& updated_android_form,
1359 const std::vector<std::string>& affiliated_web_realms) {
1360 ScheduleTask(base::BindOnce(&PasswordStore::UpdateAffiliatedWebLoginsImpl,
1361 this, updated_android_form,
1362 affiliated_web_realms));
1363 }
1364
1365 base::WeakPtr<syncer::ModelTypeControllerDelegate>
GetSyncControllerDelegateOnBackgroundSequence()1366 PasswordStore::GetSyncControllerDelegateOnBackgroundSequence() {
1367 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1368 DCHECK(sync_bridge_);
1369 return sync_bridge_->change_processor()->GetControllerDelegate();
1370 }
1371
DestroyOnBackgroundSequence()1372 void PasswordStore::DestroyOnBackgroundSequence() {
1373 DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
1374 sync_bridge_.reset();
1375
1376 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1377 delete reuse_detector_;
1378 reuse_detector_ = nullptr;
1379 #endif
1380 }
1381
1382 } // namespace password_manager
1383