1 // Copyright 2015 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 #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_ANDROID_AFFILIATION_SERVICE_H_ 6 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_ANDROID_AFFILIATION_SERVICE_H_ 7 8 #include <string> 9 10 #include "base/callback.h" 11 #include "base/macros.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/sequence_checker.h" 15 #include "components/keyed_service/core/keyed_service.h" 16 #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" 17 18 namespace base { 19 class FilePath; 20 class SequencedTaskRunner; 21 } // namespace base 22 23 namespace network { 24 class NetworkConnectionTracker; 25 class SharedURLLoaderFactory; 26 } // namespace network 27 28 namespace password_manager { 29 class AffiliationBackend; 30 31 // A service that can be used to query the list of facets that are affiliated 32 // with a given facet, i.e., facets that belong to the same logical application. 33 // See affiliation_utils.h for details of what this means. 34 // 35 // The service must be accessed from the UI thread, and it can be utilized in 36 // two ways: 37 // 38 // 1.) On-demand fetching: For the one-off query that wishes to learn 39 // affiliations of facet X when (potentially) issuing an on-demand 40 // network request to the Affiliation API containing the URI of facet X 41 // is acceptable from the privacy and/or performance perspective. 42 // 43 // This mode of operation is achieved by invoking 44 // GetAffiliationsAndBranding() with 45 // StrategyOnCacheMiss::FETCH_OVER_NETWORK. 46 // 47 // 2.) Proactive fetching: For the compound query that is concerned with 48 // checking, over time, whether or not each element in a sequence of 49 // facets, W_1, W_2, ..., W_n, is affiliated with a fixed facet Y; and 50 // when it is desired, for privacy and/or performance reasons, that only 51 // facet Y be looked up against the Affiliation API and that subsequent 52 // requests regarding each W_i not trigger additional requests. 53 // 54 // This mode of operation can be useful when, for example, the password 55 // manager has credentials stored for facet Y and wishes to check, for 56 // each visited web site W_i, whether these credentials should be offered 57 // to be autofilled onto W_i. 58 // 59 // Example code: 60 // 61 // class ExampleAffiliatedCredentialFiller 62 // : public base::SupportsWeakPtr<...> { 63 // public: 64 // ExampleAffiliatedCredentialFiller(AndroidAffiliationService* service, 65 // const FacetURI& y) 66 // : service_(service), y_(y) { 67 // cancel_handle_ = service_->Prefetch(y_, base::Time::Max()); 68 // } 69 // 70 // ~ExampleAffiliatedCredentialFiller() { cancel_handle_.Run(); } 71 // 72 // void ShouldFillInto(const FacetURI& wi, FillDelegate* delegate) { 73 // service_->GetAffiliationsAndBranding(wi, StrategyOnCacheMiss::FAIL, 74 // base::BindOnce( 75 // &ExampleAffiliatedCredentialFiller::OnAffiliationResult, 76 // AsWeakPtr(), 77 // delegate)); 78 // } 79 // 80 // void OnAffiliationResult(FillDelegate* delegate, 81 // const AffiliatedFacets& results, 82 // bool success) { 83 // if (success && std::count(results.begin(), results.end(), y_)) 84 // delegate->FillCredentialsFor(y_); 85 // } 86 // 87 // private: 88 // AndroidAffiliationService* service_; 89 // const FacetURI& y_; 90 // CancelPrefetchingHandle cancel_handle_; 91 // }; 92 class AndroidAffiliationService : public KeyedService { 93 public: 94 using ResultCallback = 95 base::OnceCallback<void(const AffiliatedFacets& /* results */, 96 bool /* success */)>; 97 98 // Controls whether to send a network request or fail on a cache miss. 99 enum class StrategyOnCacheMiss { FETCH_OVER_NETWORK, FAIL }; 100 101 // The |backend_task_runner| should be a task runner corresponding to a thread 102 // that can take blocking I/O, and is normally Chrome's DB thread. 103 explicit AndroidAffiliationService( 104 scoped_refptr<base::SequencedTaskRunner> backend_task_runner); 105 ~AndroidAffiliationService() override; 106 107 // Initializes the service by creating its backend and transferring it to the 108 // thread corresponding to |backend_task_runner_|. 109 void Initialize( 110 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, 111 network::NetworkConnectionTracker* network_connection_tracker, 112 const base::FilePath& db_path); 113 114 // Looks up facets affiliated with the facet identified by |facet_uri| and 115 // branding information, and invokes |result_callback| with the results. It is 116 // guaranteed that the results will contain one facet with URI equal to 117 // |facet_uri| when |result_callback| is invoked with success set to true. 118 // 119 // If the local cache contains fresh affiliation and branding information for 120 // |facet_uri|, the request will be served from cache. Otherwise, 121 // |cache_miss_policy| controls whether to issue an on-demand network request, 122 // or to fail the request without fetching. 123 virtual void GetAffiliationsAndBranding( 124 const FacetURI& facet_uri, 125 StrategyOnCacheMiss cache_miss_strategy, 126 ResultCallback result_callback); 127 128 // Prefetches affiliation information for the facet identified by |facet_uri|, 129 // and keeps the information fresh by periodic re-fetches (as needed) until 130 // the clock strikes |keep_fresh_until| (exclusive), until a matching call to 131 // CancelPrefetch(), or until Chrome is shut down, whichever is sooner. It is 132 // a supported use-case to pass base::Time::Max() as |keep_fresh_until|. 133 // 134 // Canceling can be useful when a password is deleted, so that resources are 135 // no longer wasted on repeatedly refreshing affiliation information. Note 136 // that canceling will not blow away data already stored in the cache unless 137 // it becomes stale. 138 virtual void Prefetch(const FacetURI& facet_uri, 139 const base::Time& keep_fresh_until); 140 141 // Cancels the corresponding prefetch command, i.e., the one issued for the 142 // same |facet_uri| and with the same |keep_fresh_until|. 143 virtual void CancelPrefetch(const FacetURI& facet_uri, 144 const base::Time& keep_fresh_until); 145 146 // Wipes results of on-demand fetches and expired prefetches from the cache, 147 // but retains information corresponding to facets that are being kept fresh. 148 // As no required data is deleted, there will be no network requests directly 149 // triggered by this call. It will only potentially remove data 150 // corresponding to the given |facet_uri|, but still only as long as the 151 // data is no longer needed. 152 virtual void TrimCacheForFacetURI(const FacetURI& facet_uri); 153 GetBackendForTesting()154 AffiliationBackend* GetBackendForTesting() { return backend_; } 155 156 private: 157 // The backend, owned by this AndroidAffiliationService instance, but living 158 // on the DB thread. It will be deleted asynchronously during shutdown on the 159 // DB thread, so it will outlive |this| along with all its in-flight tasks. 160 AffiliationBackend* backend_; 161 162 // TaskRunner to be used to run the |backend_|. 163 scoped_refptr<base::SequencedTaskRunner> backend_task_runner_; 164 165 SEQUENCE_CHECKER(sequence_checker_); 166 base::WeakPtrFactory<AndroidAffiliationService> weak_ptr_factory_{this}; 167 168 DISALLOW_COPY_AND_ASSIGN(AndroidAffiliationService); 169 }; 170 171 } // namespace password_manager 172 173 #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_ANDROID_AFFILIATION_SERVICE_H_ 174