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