blob: 5ec30d01971ec374940e08e188b629cdf5f99256 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h"
#import "base/containers/cxx20_erase.h"
#import "components/password_manager/core/browser/affiliation/affiliation_utils.h"
#import "components/password_manager/core/browser/password_form.h"
#import "components/password_manager/core/browser/password_list_sorter.h"
#import "components/password_manager/core/browser/password_store_consumer.h"
#import "components/password_manager/core/browser/password_store_interface.h"
#import "ios/chrome/browser/passwords/password_store_observer_bridge.h"
#import "ios/chrome/browser/passwords/save_passwords_consumer.h"
#import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface PasswordFetcher () <SavePasswordsConsumerDelegate,
PasswordStoreObserver> {
// The interfaces for getting and manipulating a user's saved passwords.
scoped_refptr<password_manager::PasswordStoreInterface> _profilePasswordStore;
scoped_refptr<password_manager::PasswordStoreInterface> _accountPasswordStore;
// A helper object for passing data about saved passwords from a finished
// password store request to the SavePasswordsCollectionViewController.
std::unique_ptr<ios::SavePasswordsConsumer> _savedPasswordsConsumer;
// The objects to observe changes in the Password Stores.
std::unique_ptr<PasswordStoreObserverBridge> _profileStoreObserver;
std::unique_ptr<PasswordStoreObserverBridge> _accountStoreObserver;
// URL to fetch logins for. May be empty if no filtering is needed.
GURL _URL;
// Number of fetchLoginsFromStore: calls that haven't called back yet.
NSInteger _numPendingStoreFetches;
// Last results of fetchLoginsFromStore: for `_profilePasswordStore`.
std::vector<std::unique_ptr<password_manager::PasswordForm>>
_lastFetchedProfileStoreLogins;
// Last results of fetchLoginsFromStore: for `_accountPasswordStore`.
std::vector<std::unique_ptr<password_manager::PasswordForm>>
_lastFetchedAccountStoreLogins;
}
// Delegate to send the fetchted passwords.
@property(nonatomic, weak) id<PasswordFetcherDelegate> delegate;
@end
@implementation PasswordFetcher
@synthesize delegate = _delegate;
#pragma mark - Initialization
- (instancetype)
initWithProfilePasswordStore:
(scoped_refptr<password_manager::PasswordStoreInterface>)
profilePasswordStore
accountPasswordStore:
(scoped_refptr<password_manager::PasswordStoreInterface>)
accountPasswordStore
delegate:(id<PasswordFetcherDelegate>)delegate
URL:(const GURL&)URL {
DCHECK(profilePasswordStore);
DCHECK(delegate);
self = [super init];
if (self) {
_delegate = delegate;
_profilePasswordStore = profilePasswordStore;
_accountPasswordStore = accountPasswordStore;
_savedPasswordsConsumer =
std::make_unique<ios::SavePasswordsConsumer>(self);
_URL = URL;
_profileStoreObserver = std::make_unique<PasswordStoreObserverBridge>(self);
_profilePasswordStore->AddObserver(_profileStoreObserver.get());
[self fetchLoginsFromStore:_profilePasswordStore.get()];
if (_accountPasswordStore) {
_accountStoreObserver =
std::make_unique<PasswordStoreObserverBridge>(self);
_accountPasswordStore->AddObserver(_accountStoreObserver.get());
[self fetchLoginsFromStore:_accountPasswordStore.get()];
}
}
return self;
}
- (void)dealloc {
_profilePasswordStore->RemoveObserver(_profileStoreObserver.get());
if (_accountPasswordStore) {
_accountPasswordStore->RemoveObserver(_accountStoreObserver.get());
}
}
#pragma mark - Private methods
- (void)fetchLoginsFromStore:(password_manager::PasswordStoreInterface*)store {
CHECK_GE(_numPendingStoreFetches, 0);
_numPendingStoreFetches++;
if (_URL.is_empty()) {
store->GetAutofillableLogins(_savedPasswordsConsumer->GetWeakPtr());
} else {
store->GetLogins(
{password_manager::PasswordForm::Scheme::kHtml, _URL.spec(), _URL},
_savedPasswordsConsumer->GetWeakPtr());
}
}
#pragma mark - SavePasswordsConsumerDelegate
- (void)
onGetPasswordStoreResults:
(std::vector<std::unique_ptr<password_manager::PasswordForm>>)results
fromStore:(password_manager::PasswordStoreInterface*)store {
_numPendingStoreFetches--;
CHECK_GE(_numPendingStoreFetches, 0);
// Filter out Android facet IDs and any blocked passwords.
base::EraseIf(results, [](const auto& form) {
return form->blocked_by_user ||
password_manager::IsValidAndroidFacetURI(form->signon_realm);
});
if (store == _profilePasswordStore) {
_lastFetchedProfileStoreLogins = std::move(results);
} else {
_lastFetchedAccountStoreLogins = std::move(results);
}
if (_numPendingStoreFetches > 0) {
// Wait for other fetches to complete before sending results.
return;
}
std::vector<std::unique_ptr<password_manager::PasswordForm>> combinedResults;
combinedResults.reserve(_lastFetchedProfileStoreLogins.size() +
_lastFetchedAccountStoreLogins.size());
for (const std::unique_ptr<password_manager::PasswordForm>& form :
_lastFetchedProfileStoreLogins) {
combinedResults.push_back(
std::make_unique<password_manager::PasswordForm>(*form));
}
for (const std::unique_ptr<password_manager::PasswordForm>& form :
_lastFetchedAccountStoreLogins) {
combinedResults.push_back(
std::make_unique<password_manager::PasswordForm>(*form));
}
password_manager::DuplicatesMap savedPasswordDuplicates;
password_manager::SortEntriesAndHideDuplicates(&combinedResults,
&savedPasswordDuplicates);
[self.delegate passwordFetcher:self
didFetchPasswords:std::move(combinedResults)];
}
#pragma mark - PasswordStoreObserver
- (void)loginsDidChangeInStore:
(password_manager::PasswordStoreInterface*)store {
[self fetchLoginsFromStore:store];
}
@end