| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_H_ |
| #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_H_ |
| |
| #include <memory> |
| #include <ostream> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/callback_helpers.h" |
| #include "base/callback_list.h" |
| #include "base/cancelable_callback.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/observer_list_threadsafe.h" |
| #include "base/sequenced_task_runner.h" |
| #include "base/time/time.h" |
| #include "base/types/strong_alias.h" |
| #include "build/build_config.h" |
| #include "components/password_manager/core/browser/insecure_credentials_table.h" |
| #include "components/password_manager/core/browser/password_form_digest.h" |
| #include "components/password_manager/core/browser/password_manager_metrics_util.h" |
| #include "components/password_manager/core/browser/password_store_backend.h" |
| #include "components/password_manager/core/browser/password_store_change.h" |
| #include "components/password_manager/core/browser/password_store_interface.h" |
| #include "components/password_manager/core/browser/password_store_sync.h" |
| #include "components/password_manager/core/browser/smart_bubble_stats_store.h" |
| |
| class PrefService; |
| |
| namespace syncer { |
| class ModelTypeControllerDelegate; |
| class ProxyModelTypeControllerDelegate; |
| } // namespace syncer |
| |
| namespace password_manager { |
| |
| struct PasswordForm; |
| |
| using IsAccountStore = base::StrongAlias<class IsAccountStoreTag, bool>; |
| |
| using metrics_util::GaiaPasswordHashChange; |
| |
| class AffiliatedMatchHelper; |
| class PasswordStoreConsumer; |
| class InsecureCredentialsConsumer; |
| class PasswordStoreConsumer; |
| class PasswordSyncBridge; |
| struct FieldInfo; |
| |
| // Partial, cross-platform implementation for storing form passwords. |
| // The login request/manipulation API is not threadsafe and must be used |
| // from the UI thread. |
| // PasswordStoreSync is a hidden base class because only PasswordSyncBridge |
| // needs to access these methods. |
| // TODO(crbug.com/1217071): Move PasswordStoreSync to local backend. |
| class PasswordStore : protected PasswordStoreSync, |
| public PasswordStoreInterface, |
| public SmartBubbleStatsStore { |
| public: |
| // Used to notify that unsynced credentials are about to be deleted. |
| class UnsyncedCredentialsDeletionNotifier { |
| public: |
| // Should be called from the UI thread. |
| virtual void Notify(std::vector<PasswordForm>) = 0; |
| virtual ~UnsyncedCredentialsDeletionNotifier() = default; |
| virtual base::WeakPtr<UnsyncedCredentialsDeletionNotifier> GetWeakPtr() = 0; |
| }; |
| |
| PasswordStore(); |
| |
| // Always call this too on the UI thread. |
| // TODO(crbug.bom/1218413): Move initialization into the core interface, too. |
| bool Init( |
| PrefService* prefs, |
| base::RepeatingClosure sync_enabled_or_disabled_cb = base::DoNothing()); |
| |
| // RefcountedKeyedService: |
| void ShutdownOnUIThread() override; |
| |
| // Sets the affiliation-based match |helper| that will be used by subsequent |
| // GetLogins() calls to return credentials stored not only for the requested |
| // sign-on realm, but also for affiliated Android applications and Web realms. |
| // If |helper| is null, clears the the currently set helper if any. Unless a |
| // helper is set, affiliation-based matching is disabled. The passed |helper| |
| // must already be initialized if it is non-null. |
| // TODO(crbug.bom/1218413): Inject into constructor or `Init()` instead. |
| void SetAffiliatedMatchHelper(std::unique_ptr<AffiliatedMatchHelper> helper); |
| AffiliatedMatchHelper* affiliated_match_helper() const { |
| return affiliated_match_helper_.get(); |
| } |
| |
| // PasswordStoreInterface: |
| bool IsAbleToSavePasswords() const override; |
| void AddLogin(const PasswordForm& form) override; |
| void UpdateLogin(const PasswordForm& form) override; |
| void UpdateLoginWithPrimaryKey(const PasswordForm& new_form, |
| const PasswordForm& old_primary_key) override; |
| void RemoveLogin(const PasswordForm& form) override; |
| void 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 = |
| base::NullCallback()) override; |
| void RemoveLoginsCreatedBetween(base::Time delete_begin, |
| base::Time delete_end, |
| base::OnceClosure completion) override; |
| void DisableAutoSignInForOrigins( |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter, |
| base::OnceClosure completion) override; |
| void Unblocklist(const PasswordFormDigest& form_digest, |
| base::OnceClosure completion) override; |
| void GetLogins(const PasswordFormDigest& form, |
| PasswordStoreConsumer* consumer) override; |
| void GetLoginsByPassword(const std::u16string& plain_text_password, |
| PasswordStoreConsumer* consumer) override; |
| void GetAutofillableLogins(PasswordStoreConsumer* consumer) override; |
| void GetAllLogins(PasswordStoreConsumer* consumer) override; |
| void GetAllLoginsWithAffiliationAndBrandingInformation( |
| PasswordStoreConsumer* consumer) override; |
| void AddObserver(Observer* observer) override; |
| void RemoveObserver(Observer* observer) override; |
| SmartBubbleStatsStore* GetSmartBubbleStatsStore() override; |
| |
| // SmartBubbleStatsStore: |
| void AddSiteStats(const InteractionsStats& stats) override; |
| void RemoveSiteStats(const GURL& origin_domain) override; |
| void GetSiteStats(const GURL& origin_domain, |
| PasswordStoreConsumer* consumer) override; |
| void RemoveStatisticsByOriginAndTime( |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter, |
| base::Time delete_begin, |
| base::Time delete_end, |
| base::OnceClosure completion) override; |
| |
| // Reports usage metrics for the database. |sync_username|, and |
| // |custom_passphrase_sync_enabled|, and |is_under_advanced_protection| |
| // determine some of the UMA stats that may be reported. |
| virtual void ReportMetrics(const std::string& sync_username, |
| bool custom_passphrase_sync_enabled, |
| bool is_under_advanced_protection); |
| |
| // Adds information about credentials issue on |
| // |insecure_credential.url| for |insecure_credential.username|. The |
| // first |insecure_credential.create_time| is kept, so if the record for |
| // given url and username already exists, the new one will be ignored. |
| void AddInsecureCredential(const InsecureCredential& insecure_credential); |
| |
| // Removes information about insecure credentials on |signon_realm| for |
| // |username|. |
| void RemoveInsecureCredentials(const std::string& signon_realm, |
| const std::u16string& username, |
| RemoveInsecureCredentialsReason reason); |
| |
| // Retrieves all insecure credentials and notifies |consumer| on |
| // completion. The request will be cancelled if the consumer is destroyed. |
| void GetAllInsecureCredentials(InsecureCredentialsConsumer* consumer); |
| |
| // Returns all the insecure credentials for a given site. This list also |
| // includes Android affiliated credentials. |
| void GetMatchingInsecureCredentials(const std::string& signon_realm, |
| InsecureCredentialsConsumer* consumer); |
| |
| // Adds information about field. If the record for given form_signature and |
| // field_signature already exists, the new one will be ignored. |
| void AddFieldInfo(const FieldInfo& field_info); |
| |
| // Retrieves all field info and notifies |consumer| on completion. The request |
| // will be cancelled if the consumer is destroyed. |
| void GetAllFieldInfo(PasswordStoreConsumer* consumer); |
| |
| // Removes all leaked credentials in the given date range. If |completion| is |
| // not null, it will be posted to the |main_task_runner_| after deletions have |
| // been completed. Should be called on the UI thread. |
| void RemoveFieldInfoByTime(base::Time remove_begin, |
| base::Time remove_end, |
| base::OnceClosure completion); |
| |
| // Deletes and re-creates the whole PasswordStore, unless it is already empty |
| // anyway. If |completion| is not null, it will be posted to the |
| // |main_task_runner_| once the process is complete. The bool parameter |
| // indicates whether any data was actually cleared. |
| void ClearStore(base::OnceCallback<void(bool)> completion); |
| |
| // Schedules the given |task| to be run on the PasswordStore's TaskRunner. |
| bool ScheduleTask(base::OnceClosure task); |
| |
| // For sync codebase only: instantiates a proxy controller delegate to |
| // interact with PasswordSyncBridge. Must be called from the UI thread. |
| std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> |
| CreateSyncControllerDelegate(); |
| |
| // Sets |deletion_notifier_|. Must not pass a nullptr. |
| void SetUnsyncedCredentialsDeletionNotifier( |
| std::unique_ptr<UnsyncedCredentialsDeletionNotifier> deletion_notifier); |
| |
| void SetSyncTaskTimeoutForTest(base::TimeDelta timeout); |
| |
| protected: |
| using LoginsTask = base::OnceCallback<LoginsResult()>; |
| using LoginsResultProcessor = |
| base::OnceCallback<void(LoginsReply, LoginsResult)>; |
| |
| friend class base::RefCountedThreadSafe<PasswordStore>; |
| |
| // Status of PasswordStore::Init(). |
| enum class InitStatus { |
| // Initialization status is still not determined (init hasn't started or |
| // finished yet). |
| kUnknown, |
| // Initialization is successfully finished. |
| kSuccess, |
| // There was an error during initialization and PasswordStore is not ready |
| // to save or get passwords. |
| // Removing passwords may still work. |
| kFailure, |
| }; |
| |
| ~PasswordStore() override; |
| |
| // Create a TaskRunner to be saved in |background_task_runner_|. |
| virtual scoped_refptr<base::SequencedTaskRunner> CreateBackgroundTaskRunner() |
| const; |
| |
| // Creates PasswordSyncBridge and PasswordReuseDetector instances on the |
| // background sequence. Subclasses can add more logic. Returns true on |
| // success. If |upload_phished_credentials_to_sync| is true, metadata will be |
| // dropped to force syncing, if local phished credentials information exist. |
| // Dropping metadata clears all of the information about previous syncing and |
| // force uploading all the local passwords with security issues again. |
| virtual bool InitOnBackgroundSequence(); |
| |
| // Methods below will be run in PasswordStore's own sequence. |
| // Synchronous implementation that reports usage metrics. |
| virtual void ReportMetricsImpl(const std::string& sync_username, |
| bool custom_passphrase_sync_enabled, |
| BulkCheckDone bulk_check_done) = 0; |
| |
| // Synchronous implementation to remove the given logins. |
| virtual PasswordStoreChangeList RemoveLoginsByURLAndTimeImpl( |
| const base::RepeatingCallback<bool(const GURL&)>& url_filter, |
| base::Time delete_begin, |
| base::Time delete_end) = 0; |
| |
| // Synchronous implementation to remove the given logins. |
| virtual PasswordStoreChangeList RemoveLoginsCreatedBetweenImpl( |
| base::Time delete_begin, |
| base::Time delete_end) = 0; |
| |
| // Synchronous implementation to remove the statistics. |
| virtual bool RemoveStatisticsByOriginAndTimeImpl( |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter, |
| base::Time delete_begin, |
| base::Time delete_end) = 0; |
| |
| // Synchronous implementation to disable auto sign-in. |
| virtual PasswordStoreChangeList DisableAutoSignInForOriginsImpl( |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter) = 0; |
| |
| // Synchronous implementation provided by subclasses to add the given login. |
| virtual PasswordStoreChangeList AddLoginImpl( |
| const PasswordForm& form, |
| AddLoginError* error = nullptr) = 0; |
| |
| // Synchronous implementation provided by subclasses to update the given |
| // login. |
| virtual PasswordStoreChangeList UpdateLoginImpl( |
| const PasswordForm& form, |
| UpdateLoginError* error = nullptr) = 0; |
| |
| // Synchronous implementation provided by subclasses to remove the given |
| // login. |
| virtual PasswordStoreChangeList RemoveLoginImpl(const PasswordForm& form) = 0; |
| |
| // Finds and returns all PasswordForms with the same signon_realm as |form|, |
| // or with a signon_realm that is a PSL-match to that of |form|. |
| virtual std::vector<std::unique_ptr<PasswordForm>> FillMatchingLogins( |
| const PasswordFormDigest& form) = 0; |
| |
| // Finds and returns all not-blocklisted PasswordForms with the specified |
| // |plain_text_password| stored in the credential database. |
| virtual std::vector<std::unique_ptr<PasswordForm>> |
| FillMatchingLoginsByPassword(const std::u16string& plain_text_password) = 0; |
| |
| // Synchronous implementation for manipulating with statistics. |
| virtual void AddSiteStatsImpl(const InteractionsStats& stats) = 0; |
| virtual void RemoveSiteStatsImpl(const GURL& origin_domain) = 0; |
| virtual std::vector<InteractionsStats> GetSiteStatsImpl( |
| const GURL& origin_domain) = 0; |
| |
| // Synchronous implementation for manipulating with information about |
| // insecure credentials. |
| // Returns PasswordStoreChangeList for the updated password forms. |
| virtual PasswordStoreChangeList AddInsecureCredentialImpl( |
| const InsecureCredential& insecure_credential) = 0; |
| virtual PasswordStoreChangeList RemoveInsecureCredentialsImpl( |
| const std::string& signon_realm, |
| const std::u16string& username, |
| RemoveInsecureCredentialsReason reason) = 0; |
| virtual std::vector<InsecureCredential> GetAllInsecureCredentialsImpl() = 0; |
| virtual std::vector<InsecureCredential> GetMatchingInsecureCredentialsImpl( |
| const std::string& signon_realm) = 0; |
| |
| // Synchronous implementation for manipulating with information about field |
| // info. |
| virtual void AddFieldInfoImpl(const FieldInfo& field_info) = 0; |
| virtual std::vector<FieldInfo> GetAllFieldInfoImpl() = 0; |
| virtual void RemoveFieldInfoByTimeImpl(base::Time remove_begin, |
| base::Time remove_end) = 0; |
| |
| // Synchronous implementation provided by subclasses to check whether the |
| // store is empty. |
| virtual bool IsEmpty() = 0; |
| |
| // Called by *Internal() methods once the underlying data-modifying operation |
| // has been performed. Notifies observers that password store data may have |
| // been changed. |
| void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override; |
| |
| void NotifyDeletionsHaveSynced(bool success) override; |
| |
| void NotifyUnsyncedCredentialsWillBeDeleted( |
| std::vector<PasswordForm> unsynced_credentials) override; |
| |
| // Invokes callback and notifies observers if there was a change to the list |
| // of insecure passwords. It also informs Sync about the updated password |
| // forms to sync up the changes about insecure credentials. |
| void InvokeAndNotifyAboutInsecureCredentialsChange( |
| base::OnceCallback<PasswordStoreChangeList()> callback); |
| |
| scoped_refptr<base::SequencedTaskRunner> main_task_runner() const { |
| return main_task_runner_; |
| } |
| |
| scoped_refptr<base::SequencedTaskRunner> background_task_runner() const { |
| return background_task_runner_; |
| } |
| |
| // This member is called to perform the actual interaction with the storage. |
| // TODO(crbug.com/1217071): Make private std::unique_ptr as soon as the |
| // backend is passed into the store instead of it being the store(_impl). |
| PasswordStoreBackend* backend_ = nullptr; |
| |
| private: |
| using StatsResult = std::vector<InteractionsStats>; |
| using StatsTask = base::OnceCallback<StatsResult()>; |
| |
| using InsecureCredentialsTask = |
| base::OnceCallback<std::vector<InsecureCredential>()>; |
| |
| // Called on the main thread after initialization is completed. |
| // |success| is true if initialization was successful. Sets the |
| // |init_status_|. |
| void OnInitCompleted(bool success); |
| |
| // Schedules the given |task| to be run on the PasswordStore's TaskRunner. |
| // Invokes |consumer|->OnGetPasswordStoreResults() on the caller's thread with |
| // the result. |
| void PostLoginsTaskAndReplyToConsumerWithResult( |
| PasswordStoreConsumer* consumer, |
| LoginsTask task); |
| |
| // Schedules the given |task| to be run on the PasswordStore's TaskRunner. |
| // Invokes |consumer|->OnGetPasswordStoreResults() on the caller's thread with |
| // the result, after it was post-processed by |processor|. |
| // |trace_name| is the trace to be closed before calling the consumer. |
| void PostLoginsTaskAndReplyToConsumerWithProcessedResult( |
| const char* trace_name, |
| PasswordStoreConsumer* consumer, |
| LoginsTask task, |
| LoginsResultProcessor processor); |
| |
| // Schedules the given |task| to be run on the PasswordStore's TaskRunner. |
| // Invokes |consumer|->OnGetSiteStatistics() on the caller's thread with the |
| // result. |
| void PostStatsTaskAndReplyToConsumerWithResult( |
| PasswordStoreConsumer* consumer, |
| StatsTask task); |
| |
| // Schedules the given |task| to be run on the PasswordStore's TaskRunner. |
| // Invokes |consumer|->OnGetInsecureCredentials() on the caller's thread |
| // with the result. |
| void PostInsecureCredentialsTaskAndReplyToConsumerWithResult( |
| InsecureCredentialsConsumer* consumer, |
| InsecureCredentialsTask task); |
| |
| // The following methods notify observers that the password store may have |
| // been modified via NotifyLoginsChanged(). Note that there is no guarantee |
| // that the called method will actually modify the password store data. |
| void AddLoginInternal(const PasswordForm& form); |
| void UpdateLoginInternal(const PasswordForm& form); |
| void RemoveLoginInternal(const PasswordForm& form); |
| void UpdateLoginWithPrimaryKeyInternal(const PasswordForm& new_form, |
| const PasswordForm& old_primary_key); |
| void 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); |
| void RemoveLoginsCreatedBetweenInternal(base::Time delete_begin, |
| base::Time delete_end, |
| base::OnceClosure completion); |
| void RemoveStatisticsByOriginAndTimeInternal( |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter, |
| base::Time delete_begin, |
| base::Time delete_end, |
| base::OnceClosure completion); |
| void DisableAutoSignInForOriginsInternal( |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter, |
| base::OnceClosure completion); |
| void UnblocklistInternal(const PasswordFormDigest& form_digest, |
| base::OnceClosure completion); |
| PasswordStoreChangeList RemoveCompromisedCredentialsByUrlAndTimeInternal( |
| const base::RepeatingCallback<bool(const GURL&)>& url_filter, |
| base::Time remove_begin, |
| base::Time remove_end, |
| base::OnceClosure completion); |
| |
| void RemoveFieldInfoByTimeInternal(base::Time remove_begin, |
| base::Time remove_end, |
| base::OnceClosure completion); |
| |
| void ClearStoreInternal(base::OnceCallback<void(bool)> completion); |
| |
| // Finds all PasswordForms with a signon_realm that is equal to, or is a |
| // PSL-match to that of |form|, and takes care of notifying the consumer with |
| // the results when done. |
| // Note: subclasses should implement FillMatchingLogins() instead. |
| std::vector<std::unique_ptr<PasswordForm>> GetLoginsImpl( |
| const PasswordFormDigest& form); |
| |
| // Finds all credentials with the specified |plain_text_password|. |
| // Note: subclasses should implement FillMatchingLoginsByPassword() instead. |
| std::vector<std::unique_ptr<PasswordForm>> GetLoginsByPasswordImpl( |
| const std::u16string& plain_text_password); |
| |
| // Extended version of GetMatchingInsecureCredentialsImpl that also returns |
| // credentials stored for the specified affiliated Android applications or Web |
| // realms. |
| std::vector<InsecureCredential> GetInsecureCredentialsWithAffiliationsImpl( |
| const std::string& signon_realm, |
| const std::vector<std::string>& additional_affiliated_realms); |
| |
| // Retrieves and fills in affiliation and branding information for Android |
| // credentials in |forms| and invokes |callback| with the result. Called on |
| // the main sequence. |
| void InjectAffiliationAndBrandingInformation(LoginsReply callback, |
| LoginsResult forms); |
| |
| // Schedules GetInsecureCredentialsWithAffiliationsImpl() to be run on the |
| // background sequence. |
| void ScheduleGetInsecureCredentialsWithAffiliations( |
| base::WeakPtr<InsecureCredentialsConsumer> consumer, |
| const std::string& signon_realm, |
| const std::vector<std::string>& additional_affiliated_realms); |
| |
| // Retrieves the currently stored form, if any, with the same primary key as |
| // |form|, that is, with the same signon_realm, url, username_element, |
| // username_value and password_element attributes. To be called on the |
| // background sequence. |
| std::unique_ptr<PasswordForm> GetLoginImpl(const PasswordForm& primary_key); |
| |
| // Called when a password is added or updated for an Android application, and |
| // triggers finding web sites affiliated with the Android application and |
| // propagating the new password to credentials for those web sites, if any. |
| // Called on the main sequence. |
| void FindAndUpdateAffiliatedWebLogins( |
| const PasswordForm& added_or_updated_android_form); |
| |
| // Posts FindAndUpdateAffiliatedWebLogins() to the main sequence. Should be |
| // called from the background sequence. |
| void ScheduleFindAndUpdateAffiliatedWebLogins( |
| const PasswordForm& added_or_updated_android_form); |
| |
| // Called when a password is added or updated for an Android application, and |
| // propagates these changes to credentials stored for |affiliated_web_realms| |
| // under the same username, if there are any. Called on the background |
| // sequence. |
| void UpdateAffiliatedWebLoginsImpl( |
| const PasswordForm& updated_android_form, |
| const std::vector<std::string>& affiliated_web_realms); |
| |
| // Returns the sync controller delegate for syncing passwords. It must be |
| // called on the background sequence. |
| base::WeakPtr<syncer::ModelTypeControllerDelegate> |
| GetSyncControllerDelegateOnBackgroundSequence(); |
| |
| // Schedules UpdateAffiliatedWebLoginsImpl() to run on the background |
| // sequence. Should be called from the main sequence. |
| void ScheduleUpdateAffiliatedWebLoginsImpl( |
| const PasswordForm& updated_android_form, |
| const std::vector<std::string>& affiliated_web_realms); |
| |
| // Deletes object that should be destroyed on the background sequence. |
| // WARNING: this method can be skipped on shutdown. |
| void DestroyOnBackgroundSequence(); |
| |
| // TaskRunner for tasks that run on the main sequence (usually the UI thread). |
| scoped_refptr<base::SequencedTaskRunner> main_task_runner_; |
| |
| // TaskRunner for all the background operations. |
| scoped_refptr<base::SequencedTaskRunner> background_task_runner_; |
| |
| // The observers. |
| scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_; |
| |
| std::unique_ptr<PasswordSyncBridge> sync_bridge_; |
| |
| base::RepeatingClosure sync_enabled_or_disabled_cb_; |
| |
| std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_; |
| |
| PrefService* prefs_ = nullptr; |
| |
| std::unique_ptr<UnsyncedCredentialsDeletionNotifier> deletion_notifier_; |
| |
| // A list of callbacks that should be run once all pending deletions have been |
| // sent to the Sync server. Note that the vector itself lives on the |
| // background thread, but the callbacks must be run on the main thread! |
| std::vector<base::OnceCallback<void(bool)>> deletions_have_synced_callbacks_; |
| // Timeout closure that runs if sync takes too long to propagate deletions. |
| base::CancelableOnceClosure deletions_have_synced_timeout_; |
| |
| bool shutdown_called_ = false; |
| |
| InitStatus init_status_ = InitStatus::kUnknown; |
| |
| // This is usually constant, only changed in tests. |
| base::TimeDelta sync_task_timeout_ = base::TimeDelta::FromSeconds(30); |
| |
| DISALLOW_COPY_AND_ASSIGN(PasswordStore); |
| }; |
| |
| // For testing only. |
| #if defined(UNIT_TEST) |
| inline std::ostream& operator<<(std::ostream& os, |
| const PasswordFormDigest& digest) { |
| return os << "PasswordFormDigest(scheme: " << digest.scheme |
| << ", signon_realm: " << digest.signon_realm |
| << ", url: " << digest.url << ")"; |
| } |
| #endif |
| |
| } // namespace password_manager |
| |
| #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_H_ |