Index: components/password_manager/core/browser/affiliated_match_helper.h |
diff --git a/components/password_manager/core/browser/affiliated_match_helper.h b/components/password_manager/core/browser/affiliated_match_helper.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..50c7fd2d544445f28182a196e198bf6227fc8fb6 |
--- /dev/null |
+++ b/components/password_manager/core/browser/affiliated_match_helper.h |
@@ -0,0 +1,160 @@ |
+// Copyright 2015 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_AFFILIATED_MATCH_HELPER_H_ |
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_AFFILIATED_MATCH_HELPER_H_ |
+ |
+#include <memory> |
+#include <string> |
+#include <vector> |
+ |
+#include "base/callback_forward.h" |
+#include "base/macros.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/time/time.h" |
+#include "components/password_manager/core/browser/affiliation_utils.h" |
+#include "components/password_manager/core/browser/password_store.h" |
+#include "components/password_manager/core/browser/password_store_consumer.h" |
+ |
+namespace autofill { |
+struct PasswordForm; |
+} // namespace autofill |
+ |
+namespace password_manager { |
+ |
+class AffiliationService; |
+ |
+// Interacts with the AffiliationService on behalf of the PasswordStore. |
+// For each GetLogins() request, it provides the PasswordStore with a list of |
+// additional realms that are affiliation-based matches to the observed realm. |
+// |
+// Currently, the only supported use-case is obtaining Android applications |
+// affiliated with the web site containing the observed form. This is achieved |
+// by implementing the "proactive fetching" strategy for interacting with the |
+// AffiliationService (see affiliation_service.h for details), with Android |
+// applications playing the role of facet Y. |
+// |
+// More specifically, this class prefetches affiliation information on start-up |
+// for all Android applications that the PasswordStore has credentials stored |
+// for. Then, the actual GetLogins() can be restricted to the cache, so that |
+// realms of the observed web forms will never be looked up against the |
+// Affiliation API. |
+class AffiliatedMatchHelper : public PasswordStore::Observer, |
+ public PasswordStoreConsumer { |
+ public: |
+ // Callback to returns the list of affiliated signon_realms (as per defined in |
+ // autofill::PasswordForm) to the caller. |
+ typedef base::Callback<void(const std::vector<std::string>&)> |
+ AffiliatedRealmsCallback; |
+ |
+ typedef base::Callback<void( |
+ std::vector<std::unique_ptr<autofill::PasswordForm>>)> |
+ PasswordFormsCallback; |
+ |
+ // The |password_store| must outlive |this|. Both arguments must be non-NULL, |
+ // except in tests which do not Initialize() the object. |
+ AffiliatedMatchHelper( |
+ PasswordStore* password_store, |
+ std::unique_ptr<AffiliationService> affiliation_service); |
+ ~AffiliatedMatchHelper() override; |
+ |
+ // Schedules deferred initialization. |
+ void Initialize(); |
+ |
+ // Retrieves realms of Android applications affiliated with the realm of the |
+ // |observed_form| if it is web-based. Otherwise, yields the empty list. The |
+ // |result_callback| will be invoked in both cases, on the same thread. |
+ virtual void GetAffiliatedAndroidRealms( |
+ const PasswordStore::FormDigest& observed_form, |
+ const AffiliatedRealmsCallback& result_callback); |
+ |
+ // Retrieves realms of web sites affiliated with the Android application that |
+ // |android_form| belongs to and invokes |result_callback| on the same thread; |
+ // or yields the empty list if |android_form| is not an Android credential. |
+ // NOTE: This will issue an on-demand network request against the Affiliation |
+ // API if affiliations of the Android application are not cached. However, as |
+ // long as the |android_form| is from the PasswordStore, this should rarely |
+ // happen as affiliation information for those applications are prefetched. |
+ virtual void GetAffiliatedWebRealms( |
+ const PasswordStore::FormDigest& android_form, |
+ const AffiliatedRealmsCallback& result_callback); |
+ |
+ // Retrieves realms of web sites affiliated with the Android credentials in |
+ // |forms|, sets |affiliated_web_realm| of forms, and invokes |
+ // |result_callback|. |
+ // NOTE: This will not issue an on-demand network request. If a request to |
+ // cache fails, no web realm will be injected into corresponding form. |
+ virtual void InjectAffiliatedWebRealms( |
+ std::vector<std::unique_ptr<autofill::PasswordForm>> forms, |
+ const PasswordFormsCallback& result_callback); |
+ |
+ // Removes cached affiliation data that is no longer needed. |
+ void TrimAffiliationCache(); |
+ |
+ // Returns whether or not |form| represents an Android credential. |
+ static bool IsValidAndroidCredential(const PasswordStore::FormDigest& form); |
+ |
+ // Returns whether or not |form| represents a valid Web credential for the |
+ // purposes of affiliation-based matching. |
+ static bool IsValidWebCredential(const PasswordStore::FormDigest& form); |
+ |
+ // I/O heavy initialization on start-up will be delayed by this long. |
+ // This should be high enough not to exacerbate start-up I/O contention too |
+ // much, but also low enough that the user be able log-in shortly after |
+ // browser start-up into web sites using Android credentials. |
+ // TODO(engedy): See if we can tie this instead to some meaningful event. |
+ static constexpr base::TimeDelta kInitializationDelayOnStartup = |
+ base::TimeDelta::FromSeconds(8); |
+ |
+ private: |
+ // Reads all autofillable credentials from the password store and starts |
+ // observing the store for future changes. |
+ void DoDeferredInitialization(); |
+ |
+ // Called back by AffiliationService to supply the list of facets affiliated |
+ // with |original_facet_uri| so that a GetAffiliatedAndroidRealms() call can |
+ // be completed. |
+ void CompleteGetAffiliatedAndroidRealms( |
+ const FacetURI& original_facet_uri, |
+ const AffiliatedRealmsCallback& result_callback, |
+ const AffiliatedFacets& results, |
+ bool success); |
+ |
+ // Called back by AffiliationService to supply the list of facets affiliated |
+ // with the Android application that GetAffiliatedWebRealms() was called with, |
+ // so that the call can be completed. |
+ void CompleteGetAffiliatedWebRealms( |
+ const AffiliatedRealmsCallback& result_callback, |
+ const AffiliatedFacets& results, |
+ bool success); |
+ |
+ // Called back by AffiliationService to supply the list of facets affiliated |
+ // with the Android credential in |form|. Sets |form->affiliated_web_realm|, |
+ // if |success| is true and |results| is non-empty. Invokes |barrier_closure|. |
+ void CompleteInjectAffiliatedWebRealm(autofill::PasswordForm* form, |
+ base::Closure barrier_closure, |
+ const AffiliatedFacets& results, |
+ bool success); |
+ |
+ // PasswordStore::Observer: |
+ void OnLoginsChanged(const PasswordStoreChangeList& changes) override; |
+ |
+ // PasswordStoreConsumer: |
+ void OnGetPasswordStoreResults( |
+ std::vector<std::unique_ptr<autofill::PasswordForm>> results) override; |
+ |
+ PasswordStore* const password_store_; |
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_waiting_; |
+ |
+ // Being the sole consumer of AffiliationService, |this| owns the service. |
+ std::unique_ptr<AffiliationService> affiliation_service_; |
+ |
+ base::WeakPtrFactory<AffiliatedMatchHelper> weak_ptr_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AffiliatedMatchHelper); |
+}; |
+ |
+} // namespace password_manager |
+ |
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_AFFILIATED_MATCH_HELPER_H_ |